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 2009 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/time.h> 43 #include <sys/vnode.h> 44 #include <sys/sunddi.h> 45 #include <sys/cmn_err.h> 46 47 #include <netsmb/smb_osdep.h> 48 49 #include <netsmb/smb.h> 50 #include <netsmb/smb_conn.h> 51 #include <netsmb/smb_subr.h> 52 #include <netsmb/smb_rq.h> 53 54 #include <smbfs/smbfs.h> 55 #include <smbfs/smbfs_node.h> 56 #include <smbfs/smbfs_subr.h> 57 58 /* 59 * Jan 1 1980 as 64 bit NT time. 60 * (tenths of microseconds since 1601) 61 */ 62 const uint64_t NT1980 = 11960035200ULL*10000000ULL; 63 64 /* 65 * Local functions. 66 * Not static, to aid debugging. 67 */ 68 69 int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen, 70 struct smbfattr *fap, struct smb_cred *scrp); 71 int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap, 72 struct smb_cred *scrp, uint16_t infolevel); 73 74 int smbfs_smb_statfsLM1(struct smb_share *ssp, 75 statvfs64_t *sbp, struct smb_cred *scrp); 76 int smbfs_smb_statfsLM2(struct smb_share *ssp, 77 statvfs64_t *sbp, struct smb_cred *scrp); 78 79 int smbfs_smb_setfattrNT(struct smbnode *np, int fid, 80 uint32_t attr, struct timespec *mtime, struct timespec *atime, 81 struct smb_cred *scrp); 82 83 int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid, 84 struct timespec *mtime, struct timespec *atime, 85 struct smb_cred *scrp); 86 87 int smbfs_smb_setpattr1(struct smbnode *np, 88 const char *name, int len, uint32_t attr, 89 struct timespec *mtime, struct smb_cred *scrp); 90 91 92 /* 93 * Todo: locking over-the-wire 94 */ 95 #ifdef APPLE 96 97 static int 98 smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid, 99 offset_t start, uint64_t len, int largelock, 100 struct smb_cred *scrp, uint32_t timeout) 101 { 102 struct smb_share *ssp = np->n_mount->smi_share; 103 struct smb_rq rq, *rqp = &rq; 104 struct mbchain *mbp; 105 uint8_t ltype = 0; 106 int error; 107 108 /* Shared lock for n_fid use below. */ 109 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 110 111 /* After reconnect, n_fid is invalid */ 112 if (np->n_vcgenid != ssp->ss_vcgenid) 113 return (ESTALE); 114 115 if (op == SMB_LOCK_SHARED) 116 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 117 /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */ 118 if (largelock) 119 ltype |= SMB_LOCKING_ANDX_LARGE_FILES; 120 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp); 121 if (error) 122 return (error); 123 smb_rq_getrequest(rqp, &mbp); 124 smb_rq_wstart(rqp); 125 mb_put_uint8(mbp, 0xff); /* secondary command */ 126 mb_put_uint8(mbp, 0); /* MBZ */ 127 mb_put_uint16le(mbp, 0); 128 mb_put_uint16le(mbp, np->n_fid); 129 mb_put_uint8(mbp, ltype); /* locktype */ 130 mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 131 mb_put_uint32le(mbp, timeout); /* 0 nowait, -1 infinite wait */ 132 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 133 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 134 smb_rq_wend(rqp); 135 smb_rq_bstart(rqp); 136 mb_put_uint16le(mbp, pid); 137 if (!largelock) { 138 mb_put_uint32le(mbp, start); 139 mb_put_uint32le(mbp, len); 140 } else { 141 mb_put_uint16le(mbp, 0); /* pad */ 142 mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */ 143 mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */ 144 mb_put_uint32le(mbp, len >> 32); /* LengthHigh */ 145 mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */ 146 } 147 smb_rq_bend(rqp); 148 /* 149 * Don't want to risk missing a successful 150 * unlock send or lock response, or we could 151 * lose track of an outstanding lock. 152 */ 153 if (op == SMB_LOCK_RELEASE) 154 rqp->sr_flags |= SMBR_NOINTR_SEND; 155 else 156 rqp->sr_flags |= SMBR_NOINTR_RECV; 157 158 error = smb_rq_simple(rqp); 159 smb_rq_done(rqp); 160 return (error); 161 } 162 163 int 164 smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, 165 offset_t start, uint64_t len, int largelock, 166 struct smb_cred *scrp, uint32_t timeout) 167 { 168 struct smb_share *ssp = np->n_mount->smi_share; 169 170 if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0) 171 /* 172 * TODO: use LOCK_BYTE_RANGE here. 173 */ 174 return (EINVAL); 175 176 /* 177 * XXX: compute largelock via: 178 * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? 179 */ 180 return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len, 181 largelock, scrp, timeout)); 182 } 183 184 #endif /* APPLE */ 185 186 /* 187 * Helper for smbfs_getattr 188 * Something like nfs_getattr_otw 189 */ 190 int 191 smbfs_smb_getfattr( 192 struct smbnode *np, 193 struct smbfattr *fap, 194 struct smb_cred *scrp) 195 { 196 int error; 197 198 /* 199 * This lock is necessary for FID-based calls. 200 * Lock may be writer (via open) or reader. 201 */ 202 ASSERT(np->r_lkserlock.count != 0); 203 204 /* 205 * Extended attribute directory or file. 206 */ 207 if (np->n_flag & N_XATTR) { 208 error = smbfs_xa_getfattr(np, fap, scrp); 209 return (error); 210 } 211 212 error = smbfs_smb_trans2_query(np, fap, scrp, 0); 213 if (error != EINVAL) 214 return (error); 215 216 /* fallback */ 217 error = smbfs_smb_query_info(np, NULL, 0, fap, scrp); 218 219 return (error); 220 } 221 222 /* 223 * Common function for QueryFileInfo, QueryPathInfo. 224 */ 225 int 226 smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap, 227 struct smb_cred *scrp, uint16_t infolevel) 228 { 229 struct smb_share *ssp = np->n_mount->smi_share; 230 struct smb_vc *vcp = SSTOVC(ssp); 231 struct smb_t2rq *t2p; 232 int error, svtz, timesok = 1; 233 struct mbchain *mbp; 234 struct mdchain *mdp; 235 uint16_t cmd, date, time, wattr; 236 uint64_t llongint, lsize; 237 uint32_t size, dattr; 238 239 /* 240 * Shared lock for n_fid use below. 241 * See smbfs_smb_getfattr() 242 */ 243 ASSERT(np->r_lkserlock.count != 0); 244 245 /* 246 * If we have a valid open FID, use it. 247 */ 248 if ((np->n_fidrefs > 0) && 249 (np->n_fid != SMB_FID_UNUSED) && 250 (np->n_vcgenid == ssp->ss_vcgenid)) 251 cmd = SMB_TRANS2_QUERY_FILE_INFORMATION; 252 else 253 cmd = SMB_TRANS2_QUERY_PATH_INFORMATION; 254 255 top: 256 error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p); 257 if (error) 258 return (error); 259 mbp = &t2p->t2_tparam; 260 mb_init(mbp); 261 if (!infolevel) { 262 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) 263 infolevel = SMB_QFILEINFO_STANDARD; 264 else 265 infolevel = SMB_QFILEINFO_ALL_INFO; 266 } 267 268 if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION) 269 mb_put_uint16le(mbp, np->n_fid); 270 271 mb_put_uint16le(mbp, infolevel); 272 273 if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) { 274 mb_put_uint32le(mbp, 0); 275 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 276 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 277 if (error) { 278 smb_t2_done(t2p); 279 return (error); 280 } 281 } 282 283 t2p->t2_maxpcount = 2; 284 t2p->t2_maxdcount = vcp->vc_txmax; 285 error = smb_t2_request(t2p); 286 if (error) { 287 smb_t2_done(t2p); 288 /* Invalid info level? Try fallback. */ 289 if (error == EINVAL && 290 infolevel == SMB_QFILEINFO_ALL_INFO) { 291 infolevel = SMB_QFILEINFO_STANDARD; 292 goto top; 293 } 294 return (error); 295 } 296 mdp = &t2p->t2_rdata; 297 svtz = vcp->vc_sopt.sv_tz; 298 switch (infolevel) { 299 case SMB_QFILEINFO_STANDARD: 300 md_get_uint16le(mdp, &date); 301 md_get_uint16le(mdp, &time); /* creation time */ 302 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime); 303 md_get_uint16le(mdp, &date); 304 md_get_uint16le(mdp, &time); /* access time */ 305 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); 306 md_get_uint16le(mdp, &date); 307 md_get_uint16le(mdp, &time); /* modify time */ 308 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); 309 md_get_uint32le(mdp, &size); /* EOF position */ 310 fap->fa_size = size; 311 md_get_uint32le(mdp, &size); /* allocation size */ 312 fap->fa_allocsz = size; 313 error = md_get_uint16le(mdp, &wattr); 314 fap->fa_attr = wattr; 315 timesok = 1; 316 break; 317 case SMB_QFILEINFO_ALL_INFO: 318 timesok = 0; 319 /* creation time */ 320 md_get_uint64le(mdp, &llongint); 321 if (llongint) 322 timesok++; 323 smb_time_NT2local(llongint, &fap->fa_createtime); 324 325 /* last access time */ 326 md_get_uint64le(mdp, &llongint); 327 if (llongint) 328 timesok++; 329 smb_time_NT2local(llongint, &fap->fa_atime); 330 331 /* last write time */ 332 md_get_uint64le(mdp, &llongint); 333 if (llongint) 334 timesok++; 335 smb_time_NT2local(llongint, &fap->fa_mtime); 336 337 /* last change time */ 338 md_get_uint64le(mdp, &llongint); 339 if (llongint) 340 timesok++; 341 smb_time_NT2local(llongint, &fap->fa_ctime); 342 343 /* attributes */ 344 md_get_uint32le(mdp, &dattr); 345 fap->fa_attr = dattr; 346 347 /* 348 * 4-Byte alignment - discard 349 * Specs don't talk about this. 350 */ 351 md_get_uint32le(mdp, NULL); 352 /* allocation size */ 353 md_get_uint64le(mdp, &lsize); 354 fap->fa_allocsz = lsize; 355 /* File size */ 356 error = md_get_uint64le(mdp, &lsize); 357 fap->fa_size = lsize; 358 break; 359 default: 360 SMBVDEBUG("unexpected info level %d\n", infolevel); 361 error = EINVAL; 362 } 363 smb_t2_done(t2p); 364 /* 365 * if all times are zero (observed with FAT on NT4SP6) 366 * then fall back to older info level 367 */ 368 if (!timesok) { 369 if (infolevel == SMB_QFILEINFO_ALL_INFO) { 370 infolevel = SMB_QFILEINFO_STANDARD; 371 goto top; 372 } 373 error = EINVAL; 374 } 375 return (error); 376 } 377 378 /* 379 * Support functions for _qstreaminfo 380 * Moved to smbfs_xattr.c 381 */ 382 383 int 384 smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa, 385 struct smb_cred *scrp) 386 { 387 struct smb_t2rq *t2p; 388 struct mbchain *mbp; 389 struct mdchain *mdp; 390 int error; 391 uint32_t nlen; 392 393 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 394 scrp, &t2p); 395 if (error) 396 return (error); 397 mbp = &t2p->t2_tparam; 398 mb_init(mbp); 399 mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO); 400 t2p->t2_maxpcount = 4; 401 t2p->t2_maxdcount = 4 * 3 + 512; 402 error = smb_t2_request(t2p); 403 if (error) 404 goto out; 405 406 mdp = &t2p->t2_rdata; 407 md_get_uint32le(mdp, &fsa->fsa_aflags); 408 md_get_uint32le(mdp, &fsa->fsa_maxname); 409 error = md_get_uint32le(mdp, &nlen); /* fs name length */ 410 if (error) 411 goto out; 412 413 /* 414 * Get the FS type name. 415 */ 416 bzero(fsa->fsa_tname, FSTYPSZ); 417 if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) { 418 uint16_t tmpbuf[FSTYPSZ]; 419 size_t tmplen, outlen; 420 421 if (nlen > sizeof (tmpbuf)) 422 nlen = sizeof (tmpbuf); 423 error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM); 424 tmplen = nlen / 2; /* UCS-2 chars */ 425 outlen = FSTYPSZ - 1; 426 (void) uconv_u16tou8(tmpbuf, &tmplen, 427 (uchar_t *)fsa->fsa_tname, &outlen, 428 UCONV_IN_LITTLE_ENDIAN); 429 } else { 430 if (nlen > (FSTYPSZ - 1)) 431 nlen = FSTYPSZ - 1; 432 error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM); 433 } 434 435 /* 436 * If fs_name starts with FAT, we can't set dates before 1980 437 */ 438 if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) { 439 SMB_SS_LOCK(ssp); 440 ssp->ss_flags |= SMBS_FST_FAT; 441 SMB_SS_UNLOCK(ssp); 442 } 443 444 out: 445 smb_t2_done(t2p); 446 return (0); 447 } 448 449 int 450 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp, 451 struct smb_cred *scp) 452 { 453 int error; 454 455 if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) 456 error = smbfs_smb_statfsLM2(ssp, sbp, scp); 457 else 458 error = smbfs_smb_statfsLM1(ssp, sbp, scp); 459 460 return (error); 461 } 462 463 int 464 smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp, 465 struct smb_cred *scrp) 466 { 467 struct smb_t2rq *t2p; 468 struct mbchain *mbp; 469 struct mdchain *mdp; 470 uint16_t bsize; 471 uint32_t units, bpu, funits; 472 uint64_t s, t, f; 473 int error; 474 475 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 476 scrp, &t2p); 477 if (error) 478 return (error); 479 mbp = &t2p->t2_tparam; 480 mb_init(mbp); 481 mb_put_uint16le(mbp, SMB_QFS_ALLOCATION); 482 t2p->t2_maxpcount = 4; 483 t2p->t2_maxdcount = 4 * 4 + 2; 484 error = smb_t2_request(t2p); 485 if (error) 486 goto out; 487 488 mdp = &t2p->t2_rdata; 489 md_get_uint32le(mdp, NULL); /* fs id */ 490 md_get_uint32le(mdp, &bpu); 491 md_get_uint32le(mdp, &units); 492 md_get_uint32le(mdp, &funits); 493 error = md_get_uint16le(mdp, &bsize); 494 if (error) 495 goto out; 496 s = bsize; 497 s *= bpu; 498 t = units; 499 f = funits; 500 /* 501 * Don't allow over-large blocksizes as they determine 502 * Finder List-view size granularities. On the other 503 * hand, we mustn't let the block count overflow the 504 * 31 bits available. 505 */ 506 while (s > 16 * 1024) { 507 if (t > LONG_MAX) 508 break; 509 s /= 2; 510 t *= 2; 511 f *= 2; 512 } 513 while (t > LONG_MAX) { 514 t /= 2; 515 f /= 2; 516 s *= 2; 517 } 518 sbp->f_bsize = (ulong_t)s; /* file system block size */ 519 sbp->f_blocks = t; /* total data blocks in file system */ 520 sbp->f_bfree = f; /* free blocks in fs */ 521 sbp->f_bavail = f; /* free blocks avail to non-superuser */ 522 sbp->f_files = (-1); /* total file nodes in file system */ 523 sbp->f_ffree = (-1); /* free file nodes in fs */ 524 525 out: 526 smb_t2_done(t2p); 527 return (0); 528 } 529 530 int 531 smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp, 532 struct smb_cred *scrp) 533 { 534 struct smb_rq rq, *rqp = &rq; 535 struct mdchain *mdp; 536 uint16_t units, bpu, bsize, funits; 537 uint64_t s, t, f; 538 int error; 539 540 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, 541 scrp); 542 if (error) 543 return (error); 544 smb_rq_wstart(rqp); 545 smb_rq_wend(rqp); 546 smb_rq_bstart(rqp); 547 smb_rq_bend(rqp); 548 error = smb_rq_simple(rqp); 549 if (error) 550 goto out; 551 552 smb_rq_getreply(rqp, &mdp); 553 md_get_uint16le(mdp, &units); 554 md_get_uint16le(mdp, &bpu); 555 md_get_uint16le(mdp, &bsize); 556 error = md_get_uint16le(mdp, &funits); 557 if (error) 558 goto out; 559 s = bsize; 560 s *= bpu; 561 t = units; 562 f = funits; 563 /* 564 * Don't allow over-large blocksizes as they determine 565 * Finder List-view size granularities. On the other 566 * hand, we mustn't let the block count overflow the 567 * 31 bits available. 568 */ 569 while (s > 16 * 1024) { 570 if (t > LONG_MAX) 571 break; 572 s /= 2; 573 t *= 2; 574 f *= 2; 575 } 576 while (t > LONG_MAX) { 577 t /= 2; 578 f /= 2; 579 s *= 2; 580 } 581 sbp->f_bsize = (ulong_t)s; /* file system block size */ 582 sbp->f_blocks = t; /* total data blocks in file system */ 583 sbp->f_bfree = f; /* free blocks in fs */ 584 sbp->f_bavail = f; /* free blocks avail to non-superuser */ 585 sbp->f_files = (-1); /* total file nodes in file system */ 586 sbp->f_ffree = (-1); /* free file nodes in fs */ 587 588 out: 589 smb_rq_done(rqp); 590 return (0); 591 } 592 593 int 594 smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize, 595 struct smb_cred *scrp) 596 { 597 struct smb_t2rq *t2p; 598 struct smb_vc *vcp = SSTOVC(ssp); 599 struct mbchain *mbp; 600 int error; 601 602 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 603 scrp, &t2p); 604 if (error) 605 return (error); 606 mbp = &t2p->t2_tparam; 607 mb_init(mbp); 608 mb_put_uint16le(mbp, fid); 609 if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) 610 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION); 611 else 612 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO); 613 mb_put_uint16le(mbp, 0); /* pad */ 614 mbp = &t2p->t2_tdata; 615 mb_init(mbp); 616 mb_put_uint64le(mbp, newsize); 617 t2p->t2_maxpcount = 2; 618 t2p->t2_maxdcount = 0; 619 error = smb_t2_request(t2p); 620 smb_t2_done(t2p); 621 return (error); 622 } 623 624 /*ARGSUSED*/ 625 int 626 smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp, 627 const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite) 628 { 629 struct smb_t2rq *t2p; 630 struct smb_share *ssp = np->n_mount->smi_share; 631 struct smb_vc *vcp = SSTOVC(ssp); 632 struct mbchain *mbp; 633 int32_t *ucslenp; 634 int error, cerror; 635 uint16_t fid = 0; 636 637 /* Shared lock for n_fid use below. */ 638 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 639 640 /* After reconnect, n_fid is invalid */ 641 if (np->n_vcgenid != ssp->ss_vcgenid) 642 return (ESTALE); 643 644 if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)) 645 return (ENOTSUP); 646 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 647 scrp, &t2p); 648 if (error) 649 return (error); 650 if (tdnp) { 651 error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp, 652 &fid); 653 if (error) 654 goto exit; 655 } 656 mbp = &t2p->t2_tparam; 657 mb_init(mbp); 658 mb_put_uint16le(mbp, np->n_fid); 659 mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION); 660 mb_put_uint16le(mbp, 0); /* reserved, nowadays */ 661 mbp = &t2p->t2_tdata; 662 mb_init(mbp); 663 mb_put_uint32le(mbp, overwrite); 664 mb_put_uint16le(mbp, fid); /* base for tname */ 665 mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */ 666 ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t)); 667 mbp->mb_count = 0; 668 error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE); 669 if (error) 670 goto exit; 671 mbp->mb_count--; /* don't count the null */ 672 *ucslenp = htolel(mbp->mb_count); 673 t2p->t2_maxpcount = 2; 674 t2p->t2_maxdcount = 0; 675 error = smb_t2_request(t2p); 676 exit: 677 if (fid) { 678 cerror = smbfs_smb_tmpclose(tdnp, fid, scrp); 679 if (cerror) 680 SMBVDEBUG("error %d closing %s\n", 681 cerror, tdnp->n_rpath); 682 } 683 smb_t2_done(t2p); 684 return (error); 685 } 686 687 int 688 smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp) 689 { 690 struct smb_share *ssp = np->n_mount->smi_share; 691 struct smb_rq rq, *rqp = &rq; 692 struct mbchain *mbp; 693 int error; 694 695 /* Shared lock for n_fid use below. */ 696 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 697 698 if (!(np->n_flag & NFLUSHWIRE)) 699 return (0); 700 if (np->n_fidrefs == 0) 701 return (0); /* not open */ 702 703 /* After reconnect, n_fid is invalid */ 704 if (np->n_vcgenid != ssp->ss_vcgenid) 705 return (ESTALE); 706 707 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp); 708 if (error) 709 return (error); 710 smb_rq_getrequest(rqp, &mbp); 711 smb_rq_wstart(rqp); 712 mb_put_uint16le(mbp, np->n_fid); 713 smb_rq_wend(rqp); 714 smb_rq_bstart(rqp); 715 smb_rq_bend(rqp); 716 error = smb_rq_simple(rqp); 717 smb_rq_done(rqp); 718 if (!error) { 719 mutex_enter(&np->r_statelock); 720 np->n_flag &= ~NFLUSHWIRE; 721 mutex_exit(&np->r_statelock); 722 } 723 return (error); 724 } 725 726 int 727 smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize, 728 struct smb_cred *scrp) 729 { 730 struct smb_share *ssp = np->n_mount->smi_share; 731 struct smb_rq rq, *rqp = &rq; 732 struct mbchain *mbp; 733 int error; 734 735 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 736 /* 737 * This call knows about 64-bit offsets. 738 */ 739 error = smbfs_smb_seteof(ssp, fid, newsize, scrp); 740 if (!error) { 741 mutex_enter(&np->r_statelock); 742 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 743 mutex_exit(&np->r_statelock); 744 return (0); 745 } 746 } 747 748 /* 749 * OK, so fallback to SMB_COM_WRITE, but note: 750 * it only supports 32-bit file offsets. 751 */ 752 if (newsize > UINT32_MAX) 753 return (EFBIG); 754 755 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp); 756 if (error) 757 return (error); 758 smb_rq_getrequest(rqp, &mbp); 759 smb_rq_wstart(rqp); 760 mb_put_uint16le(mbp, fid); 761 mb_put_uint16le(mbp, 0); 762 mb_put_uint32le(mbp, newsize); 763 mb_put_uint16le(mbp, 0); 764 smb_rq_wend(rqp); 765 smb_rq_bstart(rqp); 766 mb_put_uint8(mbp, SMB_DT_DATA); 767 mb_put_uint16le(mbp, 0); 768 smb_rq_bend(rqp); 769 error = smb_rq_simple(rqp); 770 smb_rq_done(rqp); 771 mutex_enter(&np->r_statelock); 772 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 773 mutex_exit(&np->r_statelock); 774 return (error); 775 } 776 777 /* 778 * Old method for getting file attributes. 779 */ 780 int 781 smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen, 782 struct smbfattr *fap, struct smb_cred *scrp) 783 { 784 struct smb_rq rq, *rqp = &rq; 785 struct smb_share *ssp = np->n_mount->smi_share; 786 struct mbchain *mbp; 787 struct mdchain *mdp; 788 uint8_t wc; 789 int error; 790 uint16_t wattr; 791 uint32_t longint; 792 793 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp); 794 if (error) 795 return (error); 796 smb_rq_getrequest(rqp, &mbp); 797 smb_rq_wstart(rqp); 798 smb_rq_wend(rqp); 799 smb_rq_bstart(rqp); 800 mb_put_uint8(mbp, SMB_DT_ASCII); 801 802 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, 803 name, &nmlen, '\\'); 804 if (error) 805 goto out; 806 smb_rq_bend(rqp); 807 error = smb_rq_simple(rqp); 808 if (error) 809 goto out; 810 smb_rq_getreply(rqp, &mdp); 811 error = md_get_uint8(mdp, &wc); 812 if (error) 813 goto out; 814 if (wc != 10) { 815 error = EBADRPC; 816 goto out; 817 } 818 md_get_uint16le(mdp, &wattr); 819 fap->fa_attr = wattr; 820 /* 821 * Be careful using the time returned here, as 822 * with FAT on NT4SP6, at least, the time returned is low 823 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 824 * over about every seven minutes! 825 */ 826 md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */ 827 smb_time_server2local(longint, 828 SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime); 829 error = md_get_uint32le(mdp, &longint); 830 fap->fa_size = longint; 831 832 out: 833 smb_rq_done(rqp); 834 return (error); 835 } 836 837 /* 838 * Set DOS file attributes. mtime should be NULL for dialects above lm10 839 */ 840 int 841 smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len, 842 uint32_t attr, struct timespec *mtime, 843 struct smb_cred *scrp) 844 { 845 struct smb_rq rq, *rqp = &rq; 846 struct smb_share *ssp = np->n_mount->smi_share; 847 struct mbchain *mbp; 848 long time; 849 int error, svtz; 850 851 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp); 852 if (error) 853 return (error); 854 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 855 smb_rq_getrequest(rqp, &mbp); 856 smb_rq_wstart(rqp); 857 mb_put_uint16le(mbp, (uint16_t)attr); 858 if (mtime) { 859 smb_time_local2server(mtime, svtz, &time); 860 } else 861 time = 0; 862 mb_put_uint32le(mbp, time); /* mtime */ 863 mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 864 smb_rq_wend(rqp); 865 smb_rq_bstart(rqp); 866 mb_put_uint8(mbp, SMB_DT_ASCII); 867 868 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\'); 869 if (error) 870 goto out; 871 mb_put_uint8(mbp, SMB_DT_ASCII); 872 if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) { 873 mb_put_padbyte(mbp); 874 mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */ 875 } 876 mb_put_uint8(mbp, 0); 877 smb_rq_bend(rqp); 878 error = smb_rq_simple(rqp); 879 880 out: 881 smb_rq_done(rqp); 882 return (error); 883 } 884 885 int 886 smbfs_smb_hideit(struct smbnode *np, const char *name, int len, 887 struct smb_cred *scrp) 888 { 889 struct smbfattr fa; 890 int error; 891 uint32_t attr; 892 893 error = smbfs_smb_query_info(np, name, len, &fa, scrp); 894 attr = fa.fa_attr; 895 if (!error && !(attr & SMB_FA_HIDDEN)) { 896 attr |= SMB_FA_HIDDEN; 897 error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp); 898 } 899 return (error); 900 } 901 902 903 int 904 smbfs_smb_unhideit(struct smbnode *np, const char *name, int len, 905 struct smb_cred *scrp) 906 { 907 struct smbfattr fa; 908 uint32_t attr; 909 int error; 910 911 error = smbfs_smb_query_info(np, name, len, &fa, scrp); 912 attr = fa.fa_attr; 913 if (!error && (attr & SMB_FA_HIDDEN)) { 914 attr &= ~SMB_FA_HIDDEN; 915 error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp); 916 } 917 return (error); 918 } 919 920 /* 921 * Set file attributes (optionally: DOS attr, atime, mtime) 922 * either by open FID or by path name (FID == -1). 923 */ 924 int 925 smbfs_smb_setfattr( 926 struct smbnode *np, 927 int fid, 928 uint32_t attr, 929 struct timespec *mtime, 930 struct timespec *atime, 931 struct smb_cred *scrp) 932 { 933 struct smb_share *ssp = np->n_mount->smi_share; 934 struct smb_vc *vcp = SSTOVC(ssp); 935 int error; 936 937 /* 938 * Normally can use the trans2 call. 939 */ 940 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 941 error = smbfs_smb_setfattrNT(np, fid, 942 attr, mtime, atime, scrp); 943 return (error); 944 } 945 946 /* 947 * Fall-back for older protocols. 948 */ 949 if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) { 950 error = smbfs_smb_setftime1(np, fid, 951 mtime, atime, scrp); 952 return (error); 953 } 954 error = smbfs_smb_setpattr1(np, NULL, 0, 955 attr, mtime, scrp); 956 return (error); 957 } 958 959 /* 960 * Set file atime and mtime. Isn't supported by core dialect. 961 */ 962 int 963 smbfs_smb_setftime1( 964 struct smbnode *np, 965 uint16_t fid, 966 struct timespec *mtime, 967 struct timespec *atime, 968 struct smb_cred *scrp) 969 { 970 struct smb_rq rq, *rqp = &rq; 971 struct smb_share *ssp = np->n_mount->smi_share; 972 struct mbchain *mbp; 973 uint16_t date, time; 974 int error, tzoff; 975 976 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp); 977 if (error) 978 return (error); 979 980 tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; 981 smb_rq_getrequest(rqp, &mbp); 982 smb_rq_wstart(rqp); 983 mb_put_uint16le(mbp, fid); 984 mb_put_uint32le(mbp, 0); /* creation time */ 985 986 if (atime) 987 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 988 else 989 time = date = 0; 990 mb_put_uint16le(mbp, date); 991 mb_put_uint16le(mbp, time); 992 if (mtime) 993 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 994 else 995 time = date = 0; 996 mb_put_uint16le(mbp, date); 997 mb_put_uint16le(mbp, time); 998 smb_rq_wend(rqp); 999 smb_rq_bstart(rqp); 1000 smb_rq_bend(rqp); 1001 error = smb_rq_simple(rqp); 1002 SMBVDEBUG("%d\n", error); 1003 smb_rq_done(rqp); 1004 return (error); 1005 } 1006 1007 /* 1008 * Set DOS file attributes, either via open FID or by path name. 1009 * Looks like this call can be used only if CAP_NT_SMBS bit is on. 1010 * 1011 * When setting via path (fid == -1): 1012 * *BASIC_INFO works with Samba, but Win2K servers say it is an 1013 * invalid information level on a SET_PATH_INFO. Note Win2K does 1014 * support *BASIC_INFO on a SET_FILE_INFO, and they support the 1015 * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure. 1016 */ 1017 int 1018 smbfs_smb_setfattrNT( 1019 struct smbnode *np, 1020 int fid, /* if fid == -1, set by path */ 1021 uint32_t attr, 1022 struct timespec *mtime, 1023 struct timespec *atime, 1024 struct smb_cred *scrp) 1025 { 1026 struct smb_t2rq *t2p; 1027 struct smb_share *ssp = np->n_mount->smi_share; 1028 struct smb_vc *vcp = SSTOVC(ssp); 1029 struct mbchain *mbp; 1030 uint64_t tm; 1031 int error; 1032 uint16_t cmd, level; 1033 1034 if (fid == -1) { 1035 cmd = SMB_TRANS2_SET_PATH_INFORMATION; 1036 } else { 1037 if (fid > UINT16_MAX) 1038 return (EINVAL); 1039 cmd = SMB_TRANS2_SET_FILE_INFORMATION; 1040 } 1041 if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) 1042 level = SMB_SFILEINFO_BASIC_INFORMATION; 1043 else 1044 level = SMB_SFILEINFO_BASIC_INFO; 1045 1046 error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p); 1047 if (error) 1048 return (error); 1049 1050 mbp = &t2p->t2_tparam; 1051 mb_init(mbp); 1052 1053 if (cmd == SMB_TRANS2_SET_FILE_INFORMATION) 1054 mb_put_uint16le(mbp, fid); 1055 1056 mb_put_uint16le(mbp, level); 1057 mb_put_uint32le(mbp, 0); /* MBZ */ 1058 1059 if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) { 1060 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 1061 if (error != 0) 1062 goto out; 1063 } 1064 1065 /* FAT file systems don't support dates earlier than 1980. */ 1066 1067 mbp = &t2p->t2_tdata; 1068 mb_init(mbp); 1069 mb_put_uint64le(mbp, 0); /* creation time */ 1070 if (atime) { 1071 smb_time_local2NT(atime, &tm); 1072 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) && 1073 tm < NT1980) 1074 tm = NT1980; 1075 } else 1076 tm = 0; 1077 mb_put_uint64le(mbp, tm); /* access time */ 1078 if (mtime) { 1079 smb_time_local2NT(mtime, &tm); 1080 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) && 1081 tm < NT1980) 1082 tm = NT1980; 1083 } else 1084 tm = 0; 1085 mb_put_uint64le(mbp, tm); /* last write time */ 1086 mb_put_uint64le(mbp, 0); /* ctime (no change) */ 1087 mb_put_uint32le(mbp, attr); 1088 mb_put_uint32le(mbp, 0); /* padding */ 1089 t2p->t2_maxpcount = 2; 1090 t2p->t2_maxdcount = 0; 1091 error = smb_t2_request(t2p); 1092 out: 1093 smb_t2_done(t2p); 1094 return (error); 1095 } 1096 1097 /* 1098 * Modern create/open of file or directory. 1099 * 1100 * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or... 1101 * then this is an open attempt, and: 1102 * If xattr then name is the stream to be opened at np, 1103 * Else np should be opened. 1104 * ...we won't touch *fidp, 1105 * ...we will set or clear *attrcacheupdated. 1106 * Else this is a creation attempt, and: 1107 * If xattr then name is the stream to create at np, 1108 * Else name is the thing to create under directory np. 1109 * ...we will return *fidp, 1110 * ...we won't touch *attrcacheupdated. 1111 * 1112 * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc. 1113 * now too, which may or may not create a new object. 1114 */ 1115 int 1116 smbfs_smb_ntcreatex( 1117 struct smbnode *np, 1118 const char *name, 1119 int nmlen, 1120 int xattr, /* is named stream? */ 1121 uint32_t req_acc, /* requested access */ 1122 uint32_t efa, /* ext. file attrs (DOS attr +) */ 1123 uint32_t share_acc, 1124 uint32_t disp, /* open disposition */ 1125 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 1126 struct smb_cred *scrp, 1127 uint16_t *fidp, 1128 uint32_t *cr_act_p, /* create action */ 1129 struct smbfattr *fap) /* optional */ 1130 { 1131 struct smb_rq rq, *rqp = &rq; 1132 struct smb_share *ssp = np->n_mount->smi_share; 1133 struct smb_vc *vcp = SSTOVC(ssp); 1134 struct mbchain *mbp; 1135 struct mdchain *mdp; 1136 struct smbfattr fa; 1137 uint8_t wc; 1138 uint32_t longint, createact; 1139 uint64_t llongint; 1140 int error; 1141 uint16_t fid, *namelenp; 1142 1143 bzero(&fa, sizeof (fa)); 1144 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); 1145 if (error) 1146 return (error); 1147 smb_rq_getrequest(rqp, &mbp); 1148 smb_rq_wstart(rqp); 1149 mb_put_uint8(mbp, 0xff); /* secondary command */ 1150 mb_put_uint8(mbp, 0); /* MBZ */ 1151 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 1152 mb_put_uint8(mbp, 0); /* MBZ */ 1153 namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t)); 1154 /* 1155 * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY 1156 * for creating nor for opening a directory. Samba ignores the bit. 1157 */ 1158 mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */ 1159 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ 1160 mb_put_uint32le(mbp, req_acc); 1161 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 1162 mb_put_uint32le(mbp, efa); 1163 mb_put_uint32le(mbp, share_acc); 1164 mb_put_uint32le(mbp, disp); 1165 mb_put_uint32le(mbp, createopt); 1166 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */ 1167 mb_put_uint8(mbp, 0); /* security flags (?) */ 1168 smb_rq_wend(rqp); 1169 smb_rq_bstart(rqp); 1170 1171 if (name == NULL) 1172 nmlen = 0; 1173 error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, 1174 xattr ? ':' : '\\'); 1175 if (error) 1176 goto done; 1177 *namelenp = htoles(nmlen); /* includes null */ 1178 smb_rq_bend(rqp); 1179 /* 1180 * Don't want to risk missing a successful 1181 * open response, or we could "leak" FIDs. 1182 */ 1183 rqp->sr_flags |= SMBR_NOINTR_RECV; 1184 error = smb_rq_simple_timed(rqp, smb_timo_open); 1185 if (error) 1186 goto done; 1187 smb_rq_getreply(rqp, &mdp); 1188 /* 1189 * spec says 26 for word count, but 34 words are defined 1190 * and observed from win2000 1191 */ 1192 error = md_get_uint8(mdp, &wc); 1193 if (error) 1194 goto done; 1195 if (wc != 26 && wc != 34 && wc != 42) { 1196 error = EBADRPC; 1197 goto done; 1198 } 1199 md_get_uint8(mdp, NULL); /* secondary cmd */ 1200 md_get_uint8(mdp, NULL); /* mbz */ 1201 md_get_uint16le(mdp, NULL); /* andxoffset */ 1202 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 1203 md_get_uint16le(mdp, &fid); /* file ID */ 1204 md_get_uint32le(mdp, &createact); /* create_action */ 1205 1206 md_get_uint64le(mdp, &llongint); /* creation time */ 1207 smb_time_NT2local(llongint, &fa.fa_createtime); 1208 md_get_uint64le(mdp, &llongint); /* access time */ 1209 smb_time_NT2local(llongint, &fa.fa_atime); 1210 md_get_uint64le(mdp, &llongint); /* write time */ 1211 smb_time_NT2local(llongint, &fa.fa_mtime); 1212 md_get_uint64le(mdp, &llongint); /* change time */ 1213 smb_time_NT2local(llongint, &fa.fa_ctime); 1214 1215 md_get_uint32le(mdp, &longint); /* attributes */ 1216 fa.fa_attr = longint; 1217 1218 md_get_uint64le(mdp, &llongint); /* allocation size */ 1219 fa.fa_allocsz = llongint; 1220 1221 md_get_uint64le(mdp, &llongint); /* EOF position */ 1222 fa.fa_size = llongint; 1223 1224 error = md_get_uint16le(mdp, NULL); /* file type */ 1225 /* other stuff we don't care about */ 1226 1227 done: 1228 smb_rq_done(rqp); 1229 if (error) 1230 return (error); 1231 1232 if (fidp) 1233 *fidp = fid; 1234 if (cr_act_p) 1235 *cr_act_p = createact; 1236 if (fap) 1237 *fap = fa; /* struct copy */ 1238 1239 return (0); 1240 } 1241 1242 static uint32_t 1243 smb_mode2rights(int mode) 1244 { 1245 mode = mode & SMB_AM_OPENMODE; 1246 uint32_t rights = 1247 STD_RIGHT_SYNCHRONIZE_ACCESS | 1248 STD_RIGHT_READ_CONTROL_ACCESS; 1249 1250 if ((mode == SMB_AM_OPENREAD) || 1251 (mode == SMB_AM_OPENRW)) { 1252 rights |= 1253 SA_RIGHT_FILE_READ_ATTRIBUTES | 1254 SA_RIGHT_FILE_READ_DATA; 1255 } 1256 1257 if ((mode == SMB_AM_OPENWRITE) || 1258 (mode == SMB_AM_OPENRW)) { 1259 rights |= 1260 SA_RIGHT_FILE_WRITE_ATTRIBUTES | 1261 SA_RIGHT_FILE_APPEND_DATA | 1262 SA_RIGHT_FILE_WRITE_DATA; 1263 } 1264 1265 if (mode == SMB_AM_OPENEXEC) { 1266 rights |= 1267 SA_RIGHT_FILE_READ_ATTRIBUTES | 1268 SA_RIGHT_FILE_EXECUTE; 1269 } 1270 1271 return (rights); 1272 } 1273 1274 static int 1275 smb_rights2mode(uint32_t rights) 1276 { 1277 int accmode = SMB_AM_OPENEXEC; /* our fallback */ 1278 1279 if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD | 1280 SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES | 1281 SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS | 1282 STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS)) 1283 accmode = SMB_AM_OPENWRITE; 1284 if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES | 1285 SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS)) 1286 accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD 1287 : SMB_AM_OPENRW; 1288 return (accmode); 1289 } 1290 1291 static int 1292 smbfs_smb_oldopen( 1293 struct smbnode *np, 1294 const char *name, 1295 int nmlen, 1296 int xattr, 1297 int accmode, 1298 struct smb_cred *scrp, 1299 uint16_t *fidp, 1300 uint16_t *granted_mode_p, 1301 smbfattr_t *fap) 1302 { 1303 struct smb_rq rq, *rqp = &rq; 1304 struct smb_share *ssp = np->n_mount->smi_share; 1305 struct smb_vc *vcp = SSTOVC(ssp); 1306 struct mbchain *mbp; 1307 struct mdchain *mdp; 1308 struct smbfattr fa; 1309 uint8_t wc; 1310 uint16_t wattr; 1311 uint32_t longint; 1312 int error; 1313 1314 bzero(&fa, sizeof (fa)); 1315 1316 /* 1317 * XXX: move to callers... 1318 * 1319 * Use DENYNONE to give unixy semantics of permitting 1320 * everything not forbidden by permissions. Ie denial 1321 * is up to server with clients/openers needing to use 1322 * advisory locks for further control. 1323 */ 1324 accmode |= SMB_SM_DENYNONE; 1325 1326 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp); 1327 if (error) 1328 return (error); 1329 smb_rq_getrequest(rqp, &mbp); 1330 smb_rq_wstart(rqp); 1331 mb_put_uint16le(mbp, accmode); 1332 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY | 1333 SMB_FA_DIR); 1334 smb_rq_wend(rqp); 1335 smb_rq_bstart(rqp); 1336 mb_put_uint8(mbp, SMB_DT_ASCII); 1337 1338 error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, 1339 xattr ? ':' : '\\'); 1340 if (error) 1341 goto done; 1342 smb_rq_bend(rqp); 1343 /* 1344 * Don't want to risk missing a successful 1345 * open response, or we could "leak" FIDs. 1346 */ 1347 rqp->sr_flags |= SMBR_NOINTR_RECV; 1348 error = smb_rq_simple_timed(rqp, smb_timo_open); 1349 if (error) 1350 goto done; 1351 smb_rq_getreply(rqp, &mdp); 1352 /* 1353 * 8/2002 a DAVE server returned wc of 15 so we ignore that. 1354 * (the actual packet length and data was correct) 1355 */ 1356 error = md_get_uint8(mdp, &wc); 1357 if (error) 1358 goto done; 1359 if (wc != 7 && wc != 15) { 1360 error = EBADRPC; 1361 goto done; 1362 } 1363 md_get_uint16le(mdp, fidp); 1364 md_get_uint16le(mdp, &wattr); 1365 fa.fa_attr = wattr; 1366 /* 1367 * Be careful using the time returned here, as 1368 * with FAT on NT4SP6, at least, the time returned is low 1369 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 1370 * over about every seven minutes! 1371 */ 1372 md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */ 1373 smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime); 1374 md_get_uint32le(mdp, &longint); 1375 fa.fa_size = longint; 1376 error = md_get_uint16le(mdp, granted_mode_p); 1377 1378 done: 1379 smb_rq_done(rqp); 1380 if (error) 1381 return (error); 1382 1383 if (fap) 1384 *fap = fa; /* struct copy */ 1385 1386 return (0); 1387 } 1388 1389 int 1390 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp, 1391 uint16_t *fidp) 1392 { 1393 struct smb_share *ssp = np->n_mount->smi_share; 1394 struct smb_vc *vcp = SSTOVC(ssp); 1395 int accmode, error; 1396 1397 /* Shared lock for n_fid use below. */ 1398 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 1399 1400 /* Can we re-use n_fid? or must we open anew? */ 1401 mutex_enter(&np->r_statelock); 1402 if (np->n_fidrefs > 0 && 1403 np->n_vcgenid == ssp->ss_vcgenid && 1404 (rights & np->n_rights) == rights) { 1405 np->n_fidrefs++; 1406 *fidp = np->n_fid; 1407 mutex_exit(&np->r_statelock); 1408 return (0); 1409 } 1410 mutex_exit(&np->r_statelock); 1411 1412 /* re-open an existing file. */ 1413 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 1414 error = smbfs_smb_ntcreatex(np, 1415 NULL, 0, 0, /* name nmlen xattr */ 1416 rights, SMB_EFA_NORMAL, 1417 NTCREATEX_SHARE_ACCESS_ALL, 1418 NTCREATEX_DISP_OPEN, 1419 0, /* create options */ 1420 scrp, fidp, 1421 NULL, NULL); /* cr_act_p fa_p */ 1422 return (error); 1423 } 1424 1425 accmode = smb_rights2mode(rights); 1426 error = smbfs_smb_oldopen(np, 1427 NULL, 0, 0, /* name nmlen xattr */ 1428 accmode, scrp, 1429 fidp, 1430 NULL, /* granted mode p */ 1431 NULL); /* fa p */ 1432 1433 return (error); 1434 } 1435 1436 int 1437 smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp) 1438 { 1439 struct smb_share *ssp = np->n_mount->smi_share; 1440 int error = 0; 1441 uint16_t oldfid = SMB_FID_UNUSED; 1442 1443 /* Shared lock for n_fid use below. */ 1444 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 1445 1446 mutex_enter(&np->r_statelock); 1447 if (fid == np->n_fid) { 1448 ASSERT(np->n_fidrefs > 0); 1449 if (--np->n_fidrefs == 0) { 1450 /* 1451 * Don't expect to find the last reference 1452 * here in tmpclose. Hard to deal with as 1453 * we don't have r_lkserlock exclusive. 1454 * Will close oldfid below. 1455 */ 1456 oldfid = np->n_fid; 1457 np->n_fid = SMB_FID_UNUSED; 1458 } 1459 } else { 1460 /* Will close the passed fid. */ 1461 oldfid = fid; 1462 } 1463 mutex_exit(&np->r_statelock); 1464 1465 if (oldfid != SMB_FID_UNUSED) 1466 error = smbfs_smb_close(ssp, oldfid, NULL, scrp); 1467 1468 return (error); 1469 } 1470 1471 int 1472 smbfs_smb_open( 1473 struct smbnode *np, 1474 const char *name, 1475 int nmlen, 1476 int xattr, 1477 uint32_t rights, 1478 struct smb_cred *scrp, 1479 uint16_t *fidp, 1480 uint32_t *rightsp, 1481 smbfattr_t *fap) 1482 { 1483 struct smb_share *ssp = np->n_mount->smi_share; 1484 struct smb_vc *vcp = SSTOVC(ssp); 1485 int accmode, error; 1486 uint16_t grantedmode; 1487 1488 /* open an existing file */ 1489 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 1490 error = smbfs_smb_ntcreatex(np, 1491 name, nmlen, xattr, 1492 rights, SMB_EFA_NORMAL, 1493 NTCREATEX_SHARE_ACCESS_ALL, 1494 NTCREATEX_DISP_OPEN, 1495 0, /* create options */ 1496 scrp, fidp, 1497 NULL, fap); /* cr_act_p fa_p */ 1498 if (error != 0) 1499 return (error); 1500 *rightsp = rights; 1501 return (0); 1502 } 1503 1504 accmode = smb_rights2mode(rights); 1505 error = smbfs_smb_oldopen(np, 1506 name, nmlen, xattr, accmode, scrp, 1507 fidp, &grantedmode, fap); 1508 if (error != 0) 1509 return (error); 1510 *rightsp = smb_mode2rights(grantedmode); 1511 (void) smbfs_smb_getfattr(np, fap, scrp); 1512 1513 return (0); 1514 } 1515 1516 int 1517 smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, 1518 struct smb_cred *scrp) 1519 { 1520 struct smb_rq rq, *rqp = &rq; 1521 struct mbchain *mbp; 1522 long time; 1523 int error; 1524 1525 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); 1526 if (error) 1527 return (error); 1528 smb_rq_getrequest(rqp, &mbp); 1529 smb_rq_wstart(rqp); 1530 mb_put_uint16le(mbp, fid); 1531 if (mtime) { 1532 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz; 1533 smb_time_local2server(mtime, sv_tz, &time); 1534 } else 1535 time = 0; 1536 mb_put_uint32le(mbp, time); 1537 smb_rq_wend(rqp); 1538 smb_rq_bstart(rqp); 1539 smb_rq_bend(rqp); 1540 1541 /* 1542 * We don't really care about the result here, but we 1543 * do need to make sure we send this out, or we could 1544 * "leak" open file handles on interrupt or timeout. 1545 * The NOINTR_SEND flag makes this request immune to 1546 * interrupt or timeout until the send is done. 1547 */ 1548 rqp->sr_flags |= SMBR_NOINTR_SEND; 1549 error = smb_rq_simple(rqp); 1550 smb_rq_done(rqp); 1551 /* 1552 * ENOTCONN isn't interesting - if the connection is closed, 1553 * so are all our FIDs - and EIO is also not interesting, 1554 * as it means a forced unmount was done. (was ENXIO) 1555 * Also ETIME, which means we sent the request but gave up 1556 * waiting before the response came back. 1557 * 1558 * Don't clog up the system log with warnings about these 1559 * uninteresting failures on closes. 1560 */ 1561 switch (error) { 1562 case ENOTCONN: 1563 case ENXIO: 1564 case EIO: 1565 case ETIME: 1566 error = 0; 1567 } 1568 return (error); 1569 } 1570 1571 static int 1572 smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen, 1573 int xattr, struct smb_cred *scrp, uint16_t *fidp) 1574 { 1575 struct smb_rq rq, *rqp = &rq; 1576 struct smb_share *ssp = dnp->n_mount->smi_share; 1577 struct mbchain *mbp; 1578 struct mdchain *mdp; 1579 struct timespec ctime; 1580 uint8_t wc; 1581 long tm; 1582 int error; 1583 uint16_t attr = SMB_FA_ARCHIVE; 1584 1585 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp); 1586 if (error) 1587 return (error); 1588 smb_rq_getrequest(rqp, &mbp); 1589 smb_rq_wstart(rqp); 1590 if (name && *name == '.') 1591 attr |= SMB_FA_HIDDEN; 1592 mb_put_uint16le(mbp, attr); /* attributes */ 1593 gethrestime(&ctime); 1594 smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm); 1595 mb_put_uint32le(mbp, tm); 1596 smb_rq_wend(rqp); 1597 smb_rq_bstart(rqp); 1598 mb_put_uint8(mbp, SMB_DT_ASCII); 1599 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen, 1600 xattr ? ':' : '\\'); 1601 if (error) 1602 goto out; 1603 smb_rq_bend(rqp); 1604 /* 1605 * Don't want to risk missing a successful 1606 * open response, or we could "leak" FIDs. 1607 */ 1608 rqp->sr_flags |= SMBR_NOINTR_RECV; 1609 error = smb_rq_simple_timed(rqp, smb_timo_open); 1610 if (error) 1611 goto out; 1612 1613 smb_rq_getreply(rqp, &mdp); 1614 md_get_uint8(mdp, &wc); 1615 if (wc != 1) { 1616 error = EBADRPC; 1617 goto out; 1618 } 1619 error = md_get_uint16le(mdp, fidp); 1620 1621 out: 1622 smb_rq_done(rqp); 1623 return (error); 1624 } 1625 1626 int 1627 smbfs_smb_create( 1628 struct smbnode *dnp, 1629 const char *name, 1630 int nmlen, 1631 int xattr, 1632 uint32_t disp, 1633 struct smb_cred *scrp, 1634 uint16_t *fidp) 1635 { 1636 struct smb_share *ssp = dnp->n_mount->smi_share; 1637 struct smb_vc *vcp = SSTOVC(ssp); 1638 uint32_t efa, rights; 1639 int error; 1640 1641 /* 1642 * At present the only access we might need is to WRITE data, 1643 * and that only if we are creating a "symlink". When/if the 1644 * access needed gets more complex it should made a parameter 1645 * and be set upstream. 1646 */ 1647 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 1648 rights = SA_RIGHT_FILE_WRITE_DATA; 1649 efa = SMB_EFA_NORMAL; 1650 if (!xattr && name && *name == '.') 1651 efa = SMB_EFA_HIDDEN; 1652 error = smbfs_smb_ntcreatex(dnp, 1653 name, nmlen, xattr, rights, efa, 1654 NTCREATEX_SHARE_ACCESS_ALL, 1655 disp, /* != NTCREATEX_DISP_OPEN */ 1656 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE, 1657 scrp, fidp, NULL, NULL); /* cr_act_p fa_p */ 1658 return (error); 1659 } 1660 1661 error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp); 1662 return (error); 1663 } 1664 1665 int 1666 smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name, 1667 int nmlen, int xattr) 1668 { 1669 struct smb_rq rq, *rqp = &rq; 1670 struct smb_share *ssp = np->n_mount->smi_share; 1671 struct mbchain *mbp; 1672 int error; 1673 1674 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp); 1675 if (error) 1676 return (error); 1677 smb_rq_getrequest(rqp, &mbp); 1678 smb_rq_wstart(rqp); 1679 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 1680 smb_rq_wend(rqp); 1681 smb_rq_bstart(rqp); 1682 mb_put_uint8(mbp, SMB_DT_ASCII); 1683 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen, 1684 xattr ? ':' : '\\'); 1685 if (!error) { 1686 smb_rq_bend(rqp); 1687 error = smb_rq_simple(rqp); 1688 } 1689 smb_rq_done(rqp); 1690 return (error); 1691 } 1692 1693 int 1694 smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, 1695 const char *tname, int tnmlen, struct smb_cred *scrp) 1696 { 1697 struct smb_rq rq, *rqp = &rq; 1698 struct smb_share *ssp = src->n_mount->smi_share; 1699 struct mbchain *mbp; 1700 int error; 1701 uint16_t fa; 1702 char sep; 1703 1704 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp); 1705 if (error) 1706 return (error); 1707 smb_rq_getrequest(rqp, &mbp); 1708 smb_rq_wstart(rqp); 1709 /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */ 1710 fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0; 1711 fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN; 1712 mb_put_uint16le(mbp, fa); 1713 smb_rq_wend(rqp); 1714 smb_rq_bstart(rqp); 1715 1716 /* 1717 * When we're not adding any component name, the 1718 * passed sep is ignored, so just pass sep=0. 1719 */ 1720 mb_put_uint8(mbp, SMB_DT_ASCII); 1721 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0); 1722 if (error) 1723 goto out; 1724 1725 /* 1726 * After XATTR directories, separator is ":" 1727 */ 1728 sep = (src->n_flag & N_XATTR) ? ':' : '\\'; 1729 mb_put_uint8(mbp, SMB_DT_ASCII); 1730 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep); 1731 if (error) 1732 goto out; 1733 1734 smb_rq_bend(rqp); 1735 error = smb_rq_simple(rqp); 1736 out: 1737 smb_rq_done(rqp); 1738 return (error); 1739 } 1740 1741 int 1742 smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, 1743 const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp) 1744 { 1745 struct smb_rq rq, *rqp = &rq; 1746 struct smb_share *ssp = src->n_mount->smi_share; 1747 struct mbchain *mbp; 1748 int error; 1749 1750 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp); 1751 if (error) 1752 return (error); 1753 smb_rq_getrequest(rqp, &mbp); 1754 smb_rq_wstart(rqp); 1755 mb_put_uint16le(mbp, SMB_TID_UNKNOWN); 1756 mb_put_uint16le(mbp, 0x20); /* delete target file */ 1757 mb_put_uint16le(mbp, flags); 1758 smb_rq_wend(rqp); 1759 smb_rq_bstart(rqp); 1760 mb_put_uint8(mbp, SMB_DT_ASCII); 1761 1762 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\'); 1763 if (error) 1764 goto out; 1765 mb_put_uint8(mbp, SMB_DT_ASCII); 1766 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\'); 1767 if (error) 1768 goto out; 1769 smb_rq_bend(rqp); 1770 error = smb_rq_simple(rqp); 1771 1772 out: 1773 smb_rq_done(rqp); 1774 return (error); 1775 } 1776 1777 static int 1778 smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len, 1779 struct smb_cred *scrp) 1780 { 1781 struct smb_rq rq, *rqp = &rq; 1782 struct smb_share *ssp = dnp->n_mount->smi_share; 1783 struct mbchain *mbp; 1784 int error; 1785 1786 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp); 1787 if (error) 1788 return (error); 1789 smb_rq_getrequest(rqp, &mbp); 1790 smb_rq_wstart(rqp); 1791 smb_rq_wend(rqp); 1792 smb_rq_bstart(rqp); 1793 mb_put_uint8(mbp, SMB_DT_ASCII); 1794 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\'); 1795 if (!error) { 1796 smb_rq_bend(rqp); 1797 error = smb_rq_simple(rqp); 1798 } 1799 smb_rq_done(rqp); 1800 return (error); 1801 } 1802 1803 int 1804 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen, 1805 struct smb_cred *scrp) 1806 { 1807 struct smb_share *ssp = dnp->n_mount->smi_share; 1808 struct smb_vc *vcp = SSTOVC(ssp); 1809 uint32_t rights; 1810 uint16_t fid; 1811 int error; 1812 1813 /* 1814 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but 1815 * just to be asking for something. The rights==0 case could 1816 * easily be broken on some old or unusual servers. 1817 */ 1818 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 1819 rights = SA_RIGHT_FILE_READ_DATA; 1820 error = smbfs_smb_ntcreatex(dnp, 1821 name, nmlen, 0, /* xattr */ 1822 rights, SMB_EFA_DIRECTORY, 1823 NTCREATEX_SHARE_ACCESS_ALL, 1824 NTCREATEX_DISP_CREATE, 1825 NTCREATEX_OPTIONS_DIRECTORY, 1826 scrp, &fid, NULL, NULL); /* cr_act_p fa_p */ 1827 if (error) 1828 return (error); 1829 (void) smbfs_smb_close(ssp, fid, NULL, scrp); 1830 return (0); 1831 } 1832 1833 error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp); 1834 return (error); 1835 } 1836 1837 int 1838 smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp) 1839 { 1840 struct smb_rq rq, *rqp = &rq; 1841 struct smb_share *ssp = np->n_mount->smi_share; 1842 struct mbchain *mbp; 1843 int error; 1844 1845 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp); 1846 if (error) 1847 return (error); 1848 smb_rq_getrequest(rqp, &mbp); 1849 smb_rq_wstart(rqp); 1850 smb_rq_wend(rqp); 1851 smb_rq_bstart(rqp); 1852 mb_put_uint8(mbp, SMB_DT_ASCII); 1853 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\'); 1854 if (!error) { 1855 smb_rq_bend(rqp); 1856 error = smb_rq_simple(rqp); 1857 } 1858 smb_rq_done(rqp); 1859 return (error); 1860 } 1861 1862 static int 1863 smbfs_smb_search(struct smbfs_fctx *ctx) 1864 { 1865 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 1866 struct smb_rq *rqp; 1867 struct mbchain *mbp; 1868 struct mdchain *mdp; 1869 uint8_t wc, bt; 1870 uint16_t ec, dlen, bc; 1871 int len, maxent, error, iseof = 0; 1872 1873 maxent = min(ctx->f_left, 1874 (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN); 1875 if (ctx->f_rq) { 1876 smb_rq_done(ctx->f_rq); 1877 ctx->f_rq = NULL; 1878 } 1879 error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, 1880 ctx->f_scred, &rqp); 1881 if (error) 1882 return (error); 1883 ctx->f_rq = rqp; 1884 smb_rq_getrequest(rqp, &mbp); 1885 smb_rq_wstart(rqp); 1886 mb_put_uint16le(mbp, maxent); /* max entries to return */ 1887 mb_put_uint16le(mbp, ctx->f_attrmask); 1888 smb_rq_wend(rqp); 1889 smb_rq_bstart(rqp); 1890 mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ 1891 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1892 len = ctx->f_wclen; 1893 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, 1894 &len, '\\'); 1895 if (error) 1896 return (error); 1897 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1898 mb_put_uint16le(mbp, 0); /* context length */ 1899 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 1900 } else { 1901 if (SMB_UNICODE_STRINGS(vcp)) { 1902 mb_put_padbyte(mbp); 1903 mb_put_uint8(mbp, 0); 1904 } 1905 mb_put_uint8(mbp, 0); 1906 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1907 mb_put_uint16le(mbp, SMB_SKEYLEN); 1908 mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1909 } 1910 smb_rq_bend(rqp); 1911 error = smb_rq_simple(rqp); 1912 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) { 1913 error = 0; 1914 iseof = 1; 1915 ctx->f_flags |= SMBFS_RDD_EOF; 1916 } else if (error) 1917 return (error); 1918 smb_rq_getreply(rqp, &mdp); 1919 error = md_get_uint8(mdp, &wc); 1920 if (error) 1921 return (error); 1922 if (wc != 1) 1923 return (iseof ? ENOENT : EBADRPC); 1924 md_get_uint16le(mdp, &ec); 1925 md_get_uint16le(mdp, &bc); 1926 md_get_uint8(mdp, &bt); 1927 error = md_get_uint16le(mdp, &dlen); 1928 if (error) 1929 return (error); 1930 if (ec == 0) 1931 return (ENOENT); 1932 ctx->f_ecnt = ec; 1933 if (bc < 3) 1934 return (EBADRPC); 1935 bc -= 3; 1936 if (bt != SMB_DT_VARIABLE) 1937 return (EBADRPC); 1938 if (dlen != bc || dlen % SMB_DENTRYLEN != 0) 1939 return (EBADRPC); 1940 return (0); 1941 } 1942 1943 1944 /*ARGSUSED*/ 1945 static int 1946 smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp, 1947 const char *wildcard, int wclen, uint16_t attr) 1948 { 1949 1950 ctx->f_type = ft_LM1; 1951 ctx->f_attrmask = attr; 1952 if (wildcard) { 1953 if (wclen == 1 && wildcard[0] == '*') { 1954 ctx->f_wildcard = "*.*"; 1955 ctx->f_wclen = 3; 1956 } else { 1957 ctx->f_wildcard = wildcard; 1958 ctx->f_wclen = wclen; 1959 } 1960 } else { 1961 ctx->f_wildcard = NULL; 1962 ctx->f_wclen = 0; 1963 } 1964 ctx->f_name = (char *)ctx->f_fname; 1965 ctx->f_namesz = 0; 1966 return (0); 1967 } 1968 1969 static int 1970 smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit) 1971 { 1972 struct mdchain *mdp; 1973 struct smb_rq *rqp; 1974 char *cp; 1975 uint8_t battr; 1976 uint16_t date, time; 1977 uint32_t size; 1978 int error; 1979 struct timespec ts; 1980 1981 if (ctx->f_ecnt == 0) { 1982 if (ctx->f_flags & SMBFS_RDD_EOF) 1983 return (ENOENT); 1984 ctx->f_left = ctx->f_limit = limit; 1985 gethrestime(&ts); 1986 error = smbfs_smb_search(ctx); 1987 if (error) 1988 return (error); 1989 } 1990 rqp = ctx->f_rq; 1991 smb_rq_getreply(rqp, &mdp); 1992 md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1993 md_get_uint8(mdp, &battr); 1994 md_get_uint16le(mdp, &time); 1995 md_get_uint16le(mdp, &date); 1996 md_get_uint32le(mdp, &size); 1997 cp = ctx->f_name; 1998 error = md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM); 1999 cp[sizeof (ctx->f_fname) - 1] = 0; 2000 cp += strlen(cp) - 1; 2001 while (*cp == ' ' && cp >= ctx->f_name) 2002 *cp-- = 0; 2003 ctx->f_attr.fa_attr = battr; 2004 smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz, 2005 &ctx->f_attr.fa_mtime); 2006 ctx->f_attr.fa_size = size; 2007 ctx->f_nmlen = strlen(ctx->f_name); 2008 ctx->f_ecnt--; 2009 ctx->f_left--; 2010 return (0); 2011 } 2012 2013 static int 2014 smbfs_smb_findcloseLM1(struct smbfs_fctx *ctx) 2015 { 2016 if (ctx->f_rq) 2017 smb_rq_done(ctx->f_rq); 2018 return (0); 2019 } 2020 2021 /* 2022 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 2023 */ 2024 static int 2025 smbfs_smb_trans2find2(struct smbfs_fctx *ctx) 2026 { 2027 struct smb_t2rq *t2p; 2028 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 2029 struct mbchain *mbp; 2030 struct mdchain *mdp; 2031 uint16_t ecnt, eos, lno, flags; 2032 int len, error; 2033 2034 if (ctx->f_t2) { 2035 smb_t2_done(ctx->f_t2); 2036 ctx->f_t2 = NULL; 2037 } 2038 flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS; 2039 if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 2040 flags |= FIND2_CLOSE_AFTER_REQUEST; 2041 ctx->f_flags |= SMBFS_RDD_NOCLOSE; 2042 } 2043 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 2044 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, 2045 ctx->f_scred, &t2p); 2046 if (error) 2047 return (error); 2048 ctx->f_t2 = t2p; 2049 mbp = &t2p->t2_tparam; 2050 mb_init(mbp); 2051 mb_put_uint16le(mbp, ctx->f_attrmask); 2052 mb_put_uint16le(mbp, ctx->f_limit); 2053 mb_put_uint16le(mbp, flags); 2054 mb_put_uint16le(mbp, ctx->f_infolevel); 2055 mb_put_uint32le(mbp, 0); 2056 len = ctx->f_wclen; 2057 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, 2058 &len, '\\'); 2059 if (error) 2060 return (error); 2061 } else { 2062 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, 2063 ctx->f_scred, &t2p); 2064 if (error) 2065 return (error); 2066 ctx->f_t2 = t2p; 2067 mbp = &t2p->t2_tparam; 2068 mb_init(mbp); 2069 mb_put_uint16le(mbp, ctx->f_Sid); 2070 mb_put_uint16le(mbp, ctx->f_limit); 2071 mb_put_uint16le(mbp, ctx->f_infolevel); 2072 /* Send whatever resume key we received... */ 2073 mb_put_uint32le(mbp, ctx->f_rkey); 2074 mb_put_uint16le(mbp, flags); 2075 /* ... and the resume name if we have one. */ 2076 if (ctx->f_rname) { 2077 /* resume file name */ 2078 mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen, 2079 MB_MSYSTEM); 2080 } 2081 /* Add trailing null - 1 byte if ASCII, 2 if Unicode */ 2082 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2083 mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */ 2084 mb_put_uint8(mbp, 0); 2085 } 2086 t2p->t2_maxpcount = 5 * 2; 2087 t2p->t2_maxdcount = 0xF000; /* 64K less some overhead */ 2088 error = smb_t2_request(t2p); 2089 if (error) 2090 return (error); 2091 2092 /* 2093 * This is the "resume name" we just sent. 2094 * We want the new one (if any) that may be 2095 * found in the response we just received and 2096 * will now begin parsing. Free the old one 2097 * now so we'll know if we found a new one. 2098 */ 2099 if (ctx->f_rname) { 2100 kmem_free(ctx->f_rname, ctx->f_rnamelen); 2101 ctx->f_rname = NULL; 2102 ctx->f_rnamelen = 0; 2103 } 2104 2105 mdp = &t2p->t2_rparam; 2106 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 2107 if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0) 2108 goto nodata; 2109 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 2110 } 2111 md_get_uint16le(mdp, &ecnt); /* entry count */ 2112 md_get_uint16le(mdp, &eos); /* end of search */ 2113 md_get_uint16le(mdp, NULL); /* EA err. off. */ 2114 error = md_get_uint16le(mdp, &lno); /* last name off. */ 2115 if (error != 0) 2116 goto nodata; 2117 2118 /* 2119 * The "end of search" flag from an XP server sometimes 2120 * comes back zero when the prior find_next returned exactly 2121 * the number of entries requested. in which case we'd try again 2122 * but the search has in fact been closed so an EBADF results. 2123 * our circumvention is to check here for a zero entry count. 2124 */ 2125 ctx->f_ecnt = ecnt; 2126 if (eos || ctx->f_ecnt == 0) 2127 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 2128 if (ctx->f_ecnt == 0) 2129 return (ENOENT); 2130 2131 /* Last Name Off (LNO) is the entry with the resume name. */ 2132 ctx->f_rnameofs = lno; 2133 ctx->f_eofs = 0; 2134 return (0); 2135 2136 nodata: 2137 /* 2138 * Failed parsing the FindFirst or FindNext response. 2139 * Force this directory listing closed, otherwise the 2140 * calling process may hang in an infinite loop. 2141 */ 2142 ctx->f_ecnt = 0; /* Force closed. */ 2143 ctx->f_flags |= SMBFS_RDD_EOF; 2144 return (EIO); 2145 } 2146 2147 static int 2148 smbfs_smb_findclose2(struct smbfs_fctx *ctx) 2149 { 2150 struct smb_rq rq, *rqp = &rq; 2151 struct mbchain *mbp; 2152 int error; 2153 2154 error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, 2155 ctx->f_scred); 2156 if (error) 2157 return (error); 2158 smb_rq_getrequest(rqp, &mbp); 2159 smb_rq_wstart(rqp); 2160 mb_put_uint16le(mbp, ctx->f_Sid); 2161 smb_rq_wend(rqp); 2162 smb_rq_bstart(rqp); 2163 smb_rq_bend(rqp); 2164 /* Ditto comments at _smb_close */ 2165 rqp->sr_flags |= SMBR_NOINTR_SEND; 2166 error = smb_rq_simple(rqp); 2167 smb_rq_done(rqp); 2168 return (error); 2169 } 2170 2171 /*ARGSUSED*/ 2172 static int 2173 smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, 2174 const char *wildcard, int wclen, uint16_t attr) 2175 { 2176 2177 ctx->f_type = ft_LM2; 2178 ctx->f_namesz = SMB_MAXFNAMELEN + 1; 2179 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2180 ctx->f_namesz *= 2; 2181 ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP); 2182 ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) 2183 < SMB_DIALECT_NTLM0_12 ? SMB_FIND_STANDARD : 2184 SMB_FIND_BOTH_DIRECTORY_INFO; 2185 ctx->f_attrmask = attr; 2186 ctx->f_wildcard = wildcard; 2187 ctx->f_wclen = wclen; 2188 return (0); 2189 } 2190 2191 static int 2192 smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit) 2193 { 2194 struct mdchain *mdp; 2195 struct smb_t2rq *t2p; 2196 char *cp; 2197 uint8_t tb; 2198 uint16_t date, time, wattr; 2199 uint32_t size, next, dattr, resumekey = 0; 2200 uint64_t llongint; 2201 int error, svtz, cnt, fxsz, nmlen, recsz; 2202 struct timespec ts; 2203 2204 if (ctx->f_ecnt == 0) { 2205 if (ctx->f_flags & SMBFS_RDD_EOF) 2206 return (ENOENT); 2207 ctx->f_left = ctx->f_limit = limit; 2208 gethrestime(&ts); 2209 error = smbfs_smb_trans2find2(ctx); 2210 if (error) 2211 return (error); 2212 ctx->f_otws++; 2213 } 2214 t2p = ctx->f_t2; 2215 mdp = &t2p->t2_rdata; 2216 svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz; 2217 switch (ctx->f_infolevel) { 2218 case SMB_FIND_STANDARD: 2219 next = 0; 2220 fxsz = 0; 2221 md_get_uint16le(mdp, &date); 2222 md_get_uint16le(mdp, &time); /* creation time */ 2223 smb_dos2unixtime(date, time, 0, svtz, 2224 &ctx->f_attr.fa_createtime); 2225 md_get_uint16le(mdp, &date); 2226 md_get_uint16le(mdp, &time); /* access time */ 2227 smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime); 2228 md_get_uint16le(mdp, &date); 2229 md_get_uint16le(mdp, &time); /* modify time */ 2230 smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime); 2231 md_get_uint32le(mdp, &size); 2232 ctx->f_attr.fa_size = size; 2233 md_get_uint32le(mdp, &size); /* allocation size */ 2234 ctx->f_attr.fa_allocsz = size; 2235 md_get_uint16le(mdp, &wattr); 2236 ctx->f_attr.fa_attr = wattr; 2237 error = md_get_uint8(mdp, &tb); 2238 if (error) 2239 goto nodata; 2240 size = nmlen = tb; 2241 fxsz = 23; 2242 recsz = next = 24 + nmlen; /* docs misses zero byte @end */ 2243 break; 2244 case SMB_FIND_DIRECTORY_INFO: 2245 case SMB_FIND_BOTH_DIRECTORY_INFO: 2246 md_get_uint32le(mdp, &next); 2247 md_get_uint32le(mdp, &resumekey); /* file index (resume key) */ 2248 md_get_uint64le(mdp, &llongint); /* creation time */ 2249 smb_time_NT2local(llongint, &ctx->f_attr.fa_createtime); 2250 md_get_uint64le(mdp, &llongint); 2251 smb_time_NT2local(llongint, &ctx->f_attr.fa_atime); 2252 md_get_uint64le(mdp, &llongint); 2253 smb_time_NT2local(llongint, &ctx->f_attr.fa_mtime); 2254 md_get_uint64le(mdp, &llongint); 2255 smb_time_NT2local(llongint, &ctx->f_attr.fa_ctime); 2256 md_get_uint64le(mdp, &llongint); /* file size */ 2257 ctx->f_attr.fa_size = llongint; 2258 md_get_uint64le(mdp, &llongint); /* alloc. size */ 2259 ctx->f_attr.fa_allocsz = llongint; 2260 md_get_uint32le(mdp, &dattr); /* ext. file attributes */ 2261 ctx->f_attr.fa_attr = dattr; 2262 error = md_get_uint32le(mdp, &size); /* name len */ 2263 if (error) 2264 goto nodata; 2265 fxsz = 64; /* size ofinfo up to filename */ 2266 if (ctx->f_infolevel == SMB_FIND_BOTH_DIRECTORY_INFO) { 2267 /* 2268 * Skip EaSize(4 bytes), a byte of ShortNameLength, 2269 * a reserved byte, and ShortName(8.3 means 24 bytes, 2270 * as Leach defined it to always be Unicode) 2271 */ 2272 error = md_get_mem(mdp, NULL, 30, MB_MSYSTEM); 2273 if (error) 2274 goto nodata; 2275 fxsz += 30; 2276 } 2277 recsz = next ? next : fxsz + size; 2278 break; 2279 default: 2280 SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel); 2281 return (EINVAL); 2282 } 2283 2284 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2285 nmlen = min(size, SMB_MAXFNAMELEN * 2); 2286 else 2287 nmlen = min(size, SMB_MAXFNAMELEN); 2288 2289 /* Allocated f_name in findopen */ 2290 ASSERT(nmlen < ctx->f_namesz); 2291 cp = ctx->f_name; 2292 2293 error = md_get_mem(mdp, cp, nmlen, MB_MSYSTEM); 2294 if (error) 2295 goto nodata; 2296 if (next) { 2297 /* How much data to skip? */ 2298 cnt = next - nmlen - fxsz; 2299 if (cnt < 0) { 2300 SMBVDEBUG("out of sync\n"); 2301 goto nodata; 2302 } 2303 if (cnt > 0) 2304 md_get_mem(mdp, NULL, cnt, MB_MSYSTEM); 2305 } 2306 /* Don't count any trailing null in the name. */ 2307 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 2308 if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0) 2309 nmlen -= 2; 2310 } else { 2311 if (nmlen && cp[nmlen - 1] == 0) 2312 nmlen--; 2313 } 2314 if (nmlen == 0) 2315 goto nodata; 2316 2317 /* 2318 * On a find-next we expect that the server will: 2319 * 1) if the continue bit is set, use the server's offset, 2320 * 2) else if the resume key is non-zero, use that offset, 2321 * 3) else if the resume name is set, use that offset, 2322 * 4) else use the server's idea of current offset. 2323 * 2324 * We always set the resume key flag. If the server returns 2325 * a resume key then we should always send it back to them. 2326 */ 2327 ctx->f_rkey = resumekey; 2328 2329 next = ctx->f_eofs + recsz; 2330 if (ctx->f_rnameofs && 2331 ctx->f_rnameofs >= ctx->f_eofs && 2332 ctx->f_rnameofs < (int)next) { 2333 /* 2334 * This entry is the "resume name". 2335 * Save it for the next request. 2336 */ 2337 if (ctx->f_rnamelen != nmlen) { 2338 if (ctx->f_rname) 2339 kmem_free(ctx->f_rname, ctx->f_rnamelen); 2340 ctx->f_rname = kmem_alloc(nmlen, KM_SLEEP); 2341 ctx->f_rnamelen = nmlen; 2342 } 2343 bcopy(ctx->f_name, ctx->f_rname, nmlen); 2344 } 2345 ctx->f_nmlen = nmlen; 2346 ctx->f_eofs = next; 2347 ctx->f_ecnt--; 2348 ctx->f_left--; 2349 2350 smbfs_fname_tolocal(ctx); 2351 return (0); 2352 2353 nodata: 2354 /* 2355 * Something bad has happened and we ran out of data 2356 * before we could parse all f_ecnt entries expected. 2357 * Force this directory listing closed, otherwise the 2358 * calling process may hang in an infinite loop. 2359 */ 2360 SMBVDEBUG("ran out of data\n"); 2361 ctx->f_ecnt = 0; /* Force closed. */ 2362 ctx->f_flags |= SMBFS_RDD_EOF; 2363 return (EIO); 2364 } 2365 2366 static int 2367 smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx) 2368 { 2369 int error = 0; 2370 if (ctx->f_name) 2371 kmem_free(ctx->f_name, ctx->f_namesz); 2372 if (ctx->f_t2) 2373 smb_t2_done(ctx->f_t2); 2374 /* 2375 * If SMBFS_RDD_FINDFIRST is still set, we were opened 2376 * but never saw a findfirst, so we don't have any 2377 * search handle to close. 2378 */ 2379 if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0) 2380 error = smbfs_smb_findclose2(ctx); 2381 return (error); 2382 } 2383 2384 int 2385 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen, 2386 int attr, struct smb_cred *scrp, 2387 struct smbfs_fctx **ctxpp) 2388 { 2389 struct smbfs_fctx *ctx; 2390 int error; 2391 2392 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 2393 2394 ctx->f_flags = SMBFS_RDD_FINDFIRST; 2395 ctx->f_dnp = dnp; 2396 ctx->f_scred = scrp; 2397 ctx->f_ssp = dnp->n_mount->smi_share; 2398 2399 if (dnp->n_flag & N_XATTR) { 2400 error = smbfs_xa_findopen(ctx, dnp, wild, wlen); 2401 goto out; 2402 } 2403 2404 if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0) { 2405 error = smbfs_smb_findopenLM1(ctx, dnp, wild, wlen, attr); 2406 } else { 2407 error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr); 2408 } 2409 2410 out: 2411 if (error) 2412 (void) smbfs_smb_findclose(ctx, scrp); 2413 else 2414 *ctxpp = ctx; 2415 return (error); 2416 } 2417 2418 int 2419 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp) 2420 { 2421 int error; 2422 2423 /* 2424 * Note: "limit" (maxcount) needs to fit in a short! 2425 */ 2426 if (limit > 0xffff) 2427 limit = 0xffff; 2428 2429 ctx->f_scred = scrp; 2430 for (;;) { 2431 bzero(&ctx->f_attr, sizeof (ctx->f_attr)); 2432 switch (ctx->f_type) { 2433 case ft_LM1: 2434 error = smbfs_smb_findnextLM1(ctx, (uint16_t)limit); 2435 break; 2436 case ft_LM2: 2437 error = smbfs_smb_findnextLM2(ctx, (uint16_t)limit); 2438 break; 2439 case ft_XA: 2440 error = smbfs_xa_findnext(ctx, (uint16_t)limit); 2441 break; 2442 default: 2443 ASSERT(0); 2444 error = EINVAL; 2445 break; 2446 } 2447 if (error) 2448 return (error); 2449 /* 2450 * Skip "." or ".." - easy now that ctx->f_name 2451 * has already been converted to utf-8 format. 2452 */ 2453 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || 2454 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && 2455 ctx->f_name[1] == '.')) 2456 continue; 2457 break; 2458 } 2459 2460 /* 2461 * Moved the smbfs_fname_tolocal(ctx) call into 2462 * the ..._findnext functions above. 2463 */ 2464 2465 ctx->f_inum = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen); 2466 return (0); 2467 } 2468 2469 2470 int 2471 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp) 2472 { 2473 int error; 2474 2475 ctx->f_scred = scrp; 2476 switch (ctx->f_type) { 2477 case ft_LM1: 2478 error = smbfs_smb_findcloseLM1(ctx); 2479 break; 2480 case ft_LM2: 2481 error = smbfs_smb_findcloseLM2(ctx); 2482 break; 2483 case ft_XA: 2484 error = smbfs_xa_findclose(ctx); 2485 break; 2486 } 2487 if (ctx->f_rname) 2488 kmem_free(ctx->f_rname, ctx->f_rnamelen); 2489 if (ctx->f_firstnm) 2490 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen); 2491 kmem_free(ctx, sizeof (*ctx)); 2492 return (error); 2493 } 2494 2495 2496 int 2497 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, 2498 struct smbfattr *fap, struct smb_cred *scrp) 2499 { 2500 struct smbfs_fctx *ctx; 2501 int error, intr; 2502 const char *name = (namep ? *namep : NULL); 2503 int nmlen = (nmlenp ? *nmlenp : 0); 2504 2505 /* This is no longer called with a null dnp */ 2506 ASSERT(dnp); 2507 2508 /* 2509 * Should not get here with "" anymore. 2510 */ 2511 if (!name || !nmlen) { 2512 DEBUG_ENTER("smbfs_smb_lookup: name is NULL"); 2513 return (EINVAL); 2514 } 2515 2516 /* 2517 * Should not get here with "." or ".." anymore. 2518 */ 2519 if ((nmlen == 1 && name[0] == '.') || 2520 (nmlen == 2 && name[0] == '.' && name[1] == '.')) { 2521 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'"); 2522 return (EINVAL); 2523 } 2524 2525 /* 2526 * XXX: Should use _qpathinfo here instead. 2527 * (if SMB_CAP_NT_SMBS) 2528 */ 2529 2530 /* 2531 * Shared lock for n_fid use (smb_flush). 2532 */ 2533 intr = dnp->n_mount->smi_flags & SMI_INT; 2534 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr)) 2535 return (EINTR); 2536 2537 /* 2538 * This hides a server bug observable in Win98: 2539 * size changes may not show until a CLOSE or a FLUSH op 2540 * XXX: Make this conditional on !NTSMBs 2541 */ 2542 error = smbfs_smb_flush(dnp, scrp); 2543 if (error) 2544 goto out; 2545 error = smbfs_smb_findopen(dnp, name, nmlen, 2546 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx); 2547 if (error) 2548 goto out; 2549 ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 2550 error = smbfs_smb_findnext(ctx, 1, scrp); 2551 if (error == 0) { 2552 *fap = ctx->f_attr; 2553 /* 2554 * Solaris smbfattr doesn't have fa_ino, 2555 * and we don't allow name==NULL in this 2556 * function anymore. 2557 */ 2558 if (namep) 2559 *namep = (const char *)smbfs_name_alloc( 2560 ctx->f_name, ctx->f_nmlen); 2561 if (nmlenp) 2562 *nmlenp = ctx->f_nmlen; 2563 } 2564 (void) smbfs_smb_findclose(ctx, scrp); 2565 2566 out: 2567 smbfs_rw_exit(&dnp->r_lkserlock); 2568 return (error); 2569 } 2570 2571 /* 2572 * OTW function to Get a security descriptor (SD). 2573 * 2574 * Note: On success, this fills in mdp->md_top, 2575 * which the caller should free. 2576 */ 2577 int 2578 smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid, 2579 struct smb_cred *scrp, uint32_t selector, 2580 mblk_t **res, uint32_t *reslen) 2581 { 2582 struct smb_ntrq *ntp; 2583 struct mbchain *mbp; 2584 struct mdchain *mdp; 2585 int error, len; 2586 2587 error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC, 2588 scrp, &ntp); 2589 if (error) 2590 return (error); 2591 2592 /* Parameters part */ 2593 mbp = &ntp->nt_tparam; 2594 mb_init(mbp); 2595 mb_put_uint16le(mbp, fid); 2596 mb_put_uint16le(mbp, 0); /* reserved */ 2597 mb_put_uint32le(mbp, selector); 2598 /* Data part (none) */ 2599 2600 /* Max. returned parameters and data. */ 2601 ntp->nt_maxpcount = 4; 2602 ntp->nt_maxdcount = *reslen; 2603 2604 error = smb_nt_request(ntp); 2605 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) 2606 goto done; 2607 *res = NULL; 2608 2609 /* 2610 * if there's more data than we said we could receive, here 2611 * is where we pick up the length of it 2612 */ 2613 mdp = &ntp->nt_rparam; 2614 md_get_uint32le(mdp, reslen); 2615 if (error) 2616 goto done; 2617 2618 /* 2619 * get the data part. 2620 */ 2621 mdp = &ntp->nt_rdata; 2622 if (mdp->md_top == NULL) { 2623 SMBVDEBUG("null md_top? fid 0x%x\n", fid); 2624 error = EBADRPC; 2625 goto done; 2626 } 2627 2628 /* 2629 * The returned parameter SD_length should match 2630 * the length of the returned data. Unfortunately, 2631 * we have to work around server bugs here. 2632 */ 2633 len = m_fixhdr(mdp->md_top); 2634 if (len != *reslen) { 2635 SMBVDEBUG("len %d *reslen %d fid 0x%x\n", 2636 len, *reslen, fid); 2637 } 2638 2639 /* 2640 * Actual data provided is < returned SD_length. 2641 * 2642 * The following "if (len < *reslen)" handles a Windows bug 2643 * observed when the underlying filesystem is FAT32. In that 2644 * case a 32 byte security descriptor comes back (S-1-1-0, ie 2645 * "Everyone") but the Parameter Block claims 44 is the length 2646 * of the security descriptor. (The Data Block length 2647 * claimed is 32. This server bug was reported against NT 2648 * first and I've personally observed it with W2K. 2649 */ 2650 if (len < *reslen) 2651 *reslen = len; 2652 2653 /* 2654 * Actual data provided is > returned SD_length. 2655 * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0) 2656 * Narrow work-around for returned SD_length==0. 2657 */ 2658 if (len > *reslen) { 2659 /* 2660 * Increase *reslen, but carefully. 2661 */ 2662 if (*reslen == 0 && len <= ntp->nt_maxdcount) 2663 *reslen = len; 2664 } 2665 error = md_get_mbuf(mdp, len, res); 2666 2667 done: 2668 if (error == 0 && *res == NULL) { 2669 ASSERT(*res); 2670 error = EBADRPC; 2671 } 2672 2673 smb_nt_done(ntp); 2674 return (error); 2675 } 2676 2677 #ifdef APPLE 2678 /* 2679 * Wrapper for _getsd() compatible with darwin code. 2680 */ 2681 int 2682 smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, 2683 uint32_t selector, struct ntsecdesc **res) 2684 { 2685 int error; 2686 uint32_t len, olen; 2687 struct mdchain *mdp, md_store; 2688 struct mbuf *m; 2689 2690 bzero(mdp, sizeof (*mdp)); 2691 len = 500; /* "overlarge" values => server errors */ 2692 again: 2693 olen = len; 2694 error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len); 2695 /* 2696 * Server may give us an error indicating that we 2697 * need a larger data buffer to receive the SD, 2698 * and the size we'll need. Use the given size, 2699 * but only after a sanity check. 2700 * 2701 * XXX: Check for specific error values here? 2702 * XXX: also ... && len <= MAX_RAW_SD_SIZE 2703 */ 2704 if (error && len > olen) 2705 goto again; 2706 2707 if (error) 2708 return (error); 2709 2710 mdp = &md_store; 2711 md_initm(mdp, m); 2712 MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK); 2713 error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM); 2714 md_done(mdp); 2715 2716 return (error); 2717 } 2718 #endif /* APPLE */ 2719 2720 /* 2721 * OTW function to Set a security descriptor (SD). 2722 * Caller data are carried in an mbchain_t. 2723 * 2724 * Note: This normally consumes mbp->mb_top, and clears 2725 * that pointer when it does. 2726 */ 2727 int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid, 2728 struct smb_cred *scrp, uint32_t selector, mblk_t **mp) 2729 { 2730 struct smb_ntrq *ntp; 2731 struct mbchain *mbp; 2732 int error; 2733 2734 error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC, 2735 scrp, &ntp); 2736 if (error) 2737 return (error); 2738 2739 /* Parameters part */ 2740 mbp = &ntp->nt_tparam; 2741 mb_init(mbp); 2742 mb_put_uint16le(mbp, fid); 2743 mb_put_uint16le(mbp, 0); /* reserved */ 2744 mb_put_uint32le(mbp, selector); 2745 2746 /* Data part */ 2747 mbp = &ntp->nt_tdata; 2748 mb_initm(mbp, *mp); 2749 *mp = NULL; /* consumed */ 2750 2751 /* No returned parameters or data. */ 2752 ntp->nt_maxpcount = 0; 2753 ntp->nt_maxdcount = 0; 2754 2755 error = smb_nt_request(ntp); 2756 smb_nt_done(ntp); 2757 2758 return (error); 2759 } 2760 2761 #ifdef APPLE 2762 /* 2763 * This function builds the SD given the various parts. 2764 */ 2765 int 2766 smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, 2767 uint32_t selector, uint16_t flags, struct ntsid *owner, 2768 struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl) 2769 { 2770 struct mbchain *mbp, mb_store; 2771 struct ntsecdesc ntsd; 2772 int error, off; 2773 2774 /* 2775 * Build the SD as its own mbuf chain and pass it to 2776 * smbfs_smb_setsec_m() 2777 */ 2778 mbp = &mb_store; 2779 mb_init(mbp); 2780 bzero(&ntsd, sizeof (ntsd)); 2781 wset_sdrevision(&ntsd); 2782 /* 2783 * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN) 2784 * We set here only those bits we can be sure must be set. The rest 2785 * are up to the caller. In particular, the caller may intentionally 2786 * set an acl PRESENT bit while giving us a null pointer for the 2787 * acl - that sets a null acl, giving access to everyone. Note also 2788 * that the AUTO_INHERITED bits should probably always be set unless 2789 * the server is NT. 2790 */ 2791 flags |= SD_SELF_RELATIVE; 2792 off = sizeof (ntsd); 2793 if (owner) { 2794 wset_sdowneroff(&ntsd, off); 2795 off += sidlen(owner); 2796 } 2797 if (group) { 2798 wset_sdgroupoff(&ntsd, off); 2799 off += sidlen(group); 2800 } 2801 if (sacl) { 2802 flags |= SD_SACL_PRESENT; 2803 wset_sdsacloff(&ntsd, off); 2804 off += acllen(sacl); 2805 } 2806 if (dacl) { 2807 flags |= SD_DACL_PRESENT; 2808 wset_sddacloff(&ntsd, off); 2809 } 2810 wset_sdflags(&ntsd, flags); 2811 mb_put_mem(mbp, (caddr_t)&ntsd, sizeof (ntsd), MB_MSYSTEM); 2812 if (owner) 2813 mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM); 2814 if (group) 2815 mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM); 2816 if (sacl) 2817 mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM); 2818 if (dacl) 2819 mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM); 2820 2821 /* 2822 * Just pass the mbuf to _setsec_m 2823 * It will clear mb_top if consumed. 2824 */ 2825 error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top); 2826 mb_done(mbp); 2827 2828 return (error); 2829 } 2830 2831 #endif /* APPLE */ 2832