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