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