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 33 /* 34 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 35 * Use is subject to license terms. 36 * 37 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/inttypes.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/smb2.h> 52 #include <netsmb/smb_conn.h> 53 #include <netsmb/smb_subr.h> 54 #include <netsmb/smb_rq.h> 55 56 #include <smbfs/smbfs.h> 57 #include <smbfs/smbfs_node.h> 58 #include <smbfs/smbfs_subr.h> 59 60 /* 61 * Jan 1 1980 as 64 bit NT time. 62 * (tenths of microseconds since 1601) 63 */ 64 const uint64_t NT1980 = 11960035200ULL*10000000ULL; 65 66 67 /* 68 * Helper for smbfs_getattr_otw 69 * used when we have an open FID 70 */ 71 int 72 smbfs_smb_getfattr( 73 struct smbnode *np, 74 smb_fh_t *fhp, 75 struct smbfattr *fap, 76 struct smb_cred *scrp) 77 { 78 struct smb_share *ssp = np->n_mount->smi_share; 79 int error; 80 81 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 82 error = smbfs_smb2_qfileinfo(ssp, &fhp->fh_fid2, fap, scrp); 83 } else { 84 error = smbfs_smb1_trans2_query(np, fhp->fh_fid1, fap, scrp); 85 } 86 87 return (error); 88 } 89 90 /* 91 * Helper for smbfs_getattr_otw 92 * used when we don't have an open FID 93 * 94 * For SMB1 we can just use the path form of trans2 query. 95 * For SMB2 we need to do an attribute-only open. 96 * See smbfs_smb2_getpattr() 97 */ 98 int 99 smbfs_smb_getpattr( 100 struct smbnode *np, 101 struct smbfattr *fap, 102 struct smb_cred *scrp) 103 { 104 struct smb_share *ssp = np->n_mount->smi_share; 105 int error; 106 107 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 108 error = smbfs_smb2_getpattr(np, fap, scrp); 109 } else { 110 uint16_t fid = SMB_FID_UNUSED; 111 error = smbfs_smb1_trans2_query(np, fid, fap, scrp); 112 } 113 114 return (error); 115 } 116 117 /* 118 * Get and parse FileFsAttributeInformation 119 */ 120 int 121 smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa, 122 struct smb_cred *scrp) 123 { 124 int error; 125 126 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 127 error = smbfs_smb2_qfsattr(ssp, fsa, scrp); 128 } else { 129 error = smbfs_smb1_qfsattr(ssp, fsa, scrp); 130 } 131 132 /* 133 * If fs_name starts with FAT, we can't set dates before 1980 134 */ 135 if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) { 136 SMB_SS_LOCK(ssp); 137 ssp->ss_flags |= SMBS_FST_FAT; 138 SMB_SS_UNLOCK(ssp); 139 } 140 141 return (error); 142 } 143 144 int 145 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp, 146 struct smb_cred *scp) 147 { 148 struct smb_fs_size_info info; 149 struct smb_vc *vcp = SSTOVC(ssp); 150 uint32_t bps, spu; 151 int error; 152 153 if (vcp->vc_flags & SMBV_SMB2) { 154 error = smbfs_smb2_statfs(ssp, &info, scp); 155 } else { 156 error = smbfs_smb1_statfs(ssp, &info, scp); 157 } 158 if (error) 159 return (error); 160 161 /* A bit of paranoia. */ 162 bps = info.bytes_per_sect; 163 if (bps < DEV_BSIZE) 164 bps = DEV_BSIZE; 165 spu = info.sect_per_unit; 166 if (spu == 0) 167 spu = 1; 168 169 /* preferred file system block size */ 170 sbp->f_bsize = bps * spu; 171 172 /* file system block size ("fragment size") */ 173 sbp->f_frsize = bps; 174 175 /* total blocks of f_frsize */ 176 sbp->f_blocks = info.total_units * spu; 177 178 /* free blocks of f_frsize */ 179 sbp->f_bfree = info.actual_avail * spu; 180 181 /* free blocks avail to non-superuser */ 182 sbp->f_bavail = info.caller_avail * spu; 183 184 sbp->f_files = (-1); /* total file nodes in file system */ 185 sbp->f_ffree = (-1); /* free file nodes in fs */ 186 187 return (error); 188 } 189 190 int 191 smbfs_smb_setdisp(struct smb_share *ssp, smb_fh_t *fhp, 192 uint8_t disp, struct smb_cred *scrp) 193 { 194 int err; 195 196 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 197 err = smbfs_smb2_setdisp(ssp, &fhp->fh_fid2, disp, scrp); 198 } else { 199 err = smbfs_smb1_setdisp(ssp, fhp->fh_fid1, disp, scrp); 200 } 201 202 return (err); 203 } 204 205 int 206 smbfs_smb_setfsize(struct smb_share *ssp, smb_fh_t *fhp, 207 uint64_t size, struct smb_cred *scrp) 208 { 209 int error; 210 211 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 212 error = smbfs_smb2_seteof(ssp, &fhp->fh_fid2, size, scrp); 213 } else { 214 error = smbfs_smb1_seteof(ssp, fhp->fh_fid1, size, scrp); 215 } 216 217 return (error); 218 } 219 220 221 /* 222 * Set file attributes (optionally: DOS attr, atime, mtime) 223 * Always have an open FID with set attr rights. 224 */ 225 int 226 smbfs_smb_setfattr( 227 struct smb_share *ssp, 228 smb_fh_t *fhp, 229 uint32_t attr, 230 struct timespec *mtime, 231 struct timespec *atime, 232 struct smb_cred *scrp) 233 { 234 struct mbchain mb_info; 235 struct mbchain *mbp = &mb_info; 236 uint64_t tm; 237 int error; 238 239 /* 240 * Build a struct FILE_BASIC_INFORMATION in mbp 241 * LARGE_INTEGER CreationTime; 242 * LARGE_INTEGER LastAccessTime; 243 * LARGE_INTEGER LastWriteTime; 244 * LARGE_INTEGER ChangeTime; 245 * ULONG FileAttributes; 246 * Zero in times means "no change". 247 */ 248 mb_init(mbp); 249 mb_put_uint64le(mbp, 0); /* creation time */ 250 if (atime) { 251 smb_time_local2NT(atime, &tm); 252 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) && 253 tm < NT1980) 254 tm = NT1980; 255 } else 256 tm = 0; 257 mb_put_uint64le(mbp, tm); /* last access time */ 258 if (mtime) { 259 smb_time_local2NT(mtime, &tm); 260 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) && 261 tm < NT1980) 262 tm = NT1980; 263 } else 264 tm = 0; 265 mb_put_uint64le(mbp, tm); /* last write time */ 266 mb_put_uint64le(mbp, 0); /* change time */ 267 mb_put_uint32le(mbp, attr); 268 269 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 270 error = smbfs_smb2_setfattr(ssp, &fhp->fh_fid2, mbp, scrp); 271 } else { 272 error = smbfs_smb1_setfattr(ssp, fhp->fh_fid1, mbp, scrp); 273 } 274 275 return (error); 276 } 277 278 int 279 smbfs_smb_flush(struct smb_share *ssp, smb_fh_t *fhp, 280 struct smb_cred *scrp) 281 { 282 int error; 283 284 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 285 error = smbfs_smb2_flush(ssp, &fhp->fh_fid2, scrp); 286 } else { 287 error = smbfs_smb1_flush(ssp, fhp->fh_fid1, scrp); 288 } 289 return (error); 290 } 291 292 /* 293 * Modern create/open of file or directory. 294 * On success, fills in fhp->fh_fid* and fhp->fh_rights 295 */ 296 int 297 smbfs_smb_ntcreatex( 298 struct smbnode *np, 299 const char *name, 300 int nmlen, 301 int xattr, /* is named stream? */ 302 uint32_t req_acc, /* requested access */ 303 uint32_t efa, /* ext. file attrs (DOS attr +) */ 304 uint32_t share_acc, 305 uint32_t disp, /* open disposition */ 306 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 307 struct smb_cred *scrp, 308 smb_fh_t *fhp, /* pre-made file handle to fill in */ 309 uint32_t *cr_act_p, /* optional returned create action */ 310 struct smbfattr *fap) /* optional returned attributes */ 311 { 312 struct mbchain name_mb; 313 struct smb_share *ssp = np->n_mount->smi_share; 314 int err; 315 316 mb_init(&name_mb); 317 318 if (name == NULL) 319 nmlen = 0; 320 err = smbfs_fullpath(&name_mb, SSTOVC(ssp), 321 np, name, nmlen, xattr ? ':' : '\\'); 322 if (err) 323 goto out; 324 325 err = smb_smb_ntcreate(ssp, &name_mb, 326 0, /* NTCREATEX_FLAGS... */ 327 req_acc, efa, share_acc, disp, createopt, 328 NTCREATEX_IMPERSONATION_IMPERSONATION, 329 scrp, fhp, cr_act_p, fap); 330 331 out: 332 mb_done(&name_mb); 333 334 return (err); 335 } 336 337 /* 338 * Get a file handle with (at least) the specified rights. 339 * 340 * We'll try to borrow the node ->n_fid if we can. When we 341 * borrow n_fid, just take a hold on the smb_fh_t, and don't 342 * bump n_fidrefs as that tracks VFS-level opens. Similarly 343 * in _tmpclose we just release the smb_fh_t, not n_fidrefs. 344 */ 345 int 346 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp, 347 smb_fh_t **fhpp) 348 { 349 struct smb_share *ssp = np->n_mount->smi_share; 350 smb_fh_t *fhp = NULL; 351 int error; 352 353 /* Can we re-use n_fid? or must we open anew? */ 354 mutex_enter(&np->r_statelock); 355 if (np->n_fidrefs > 0 && 356 (fhp = np->n_fid) != NULL && 357 fhp->fh_vcgenid == ssp->ss_vcgenid && 358 (fhp->fh_rights & rights) == rights) { 359 smb_fh_hold(fhp); 360 *fhpp = fhp; 361 mutex_exit(&np->r_statelock); 362 return (0); 363 } 364 mutex_exit(&np->r_statelock); 365 366 error = smb_fh_create(ssp, &fhp); 367 if (error != 0) 368 goto out; 369 370 /* re-open an existing file. */ 371 error = smbfs_smb_ntcreatex(np, 372 NULL, 0, 0, /* name nmlen xattr */ 373 rights, SMB_EFA_NORMAL, 374 NTCREATEX_SHARE_ACCESS_ALL, 375 NTCREATEX_DISP_OPEN, 376 0, /* create options */ 377 scrp, fhp, 378 NULL, NULL); /* cr_act_p fa_p */ 379 if (error != 0) 380 goto out; 381 382 fhp->fh_rights = rights; 383 smb_fh_opened(fhp); 384 *fhpp = fhp; 385 fhp = NULL; 386 387 out: 388 if (fhp != NULL) 389 smb_fh_rele(fhp); 390 391 return (error); 392 } 393 394 /* ARGSUSED */ 395 void 396 smbfs_smb_tmpclose(struct smbnode *np, smb_fh_t *fhp) 397 { 398 smb_fh_rele(fhp); 399 } 400 401 int 402 smbfs_smb_open( 403 struct smbnode *np, 404 const char *name, 405 int nmlen, 406 int xattr, 407 uint32_t rights, 408 struct smb_cred *scrp, 409 smb_fh_t **fhpp, 410 smbfattr_t *fap) 411 { 412 struct smb_share *ssp = np->n_mount->smi_share; 413 // struct smb_vc *vcp = SSTOVC(ssp); 414 smb_fh_t *fhp = NULL; 415 int error; 416 417 error = smb_fh_create(ssp, &fhp); 418 if (error != 0) 419 goto out; 420 421 /* open an existing file */ 422 error = smbfs_smb_ntcreatex(np, 423 name, nmlen, xattr, 424 rights, SMB_EFA_NORMAL, 425 NTCREATEX_SHARE_ACCESS_ALL, 426 NTCREATEX_DISP_OPEN, 427 0, /* create options */ 428 scrp, fhp, NULL, fap); 429 if (error != 0) 430 goto out; 431 432 fhp->fh_rights = rights; 433 smb_fh_opened(fhp); 434 *fhpp = fhp; 435 fhp = NULL; 436 437 out: 438 if (fhp != NULL) 439 smb_fh_rele(fhp); 440 441 return (0); 442 } 443 444 void 445 smbfs_smb_close(smb_fh_t *fhp) 446 { 447 448 smb_fh_close(fhp); 449 smb_fh_rele(fhp); 450 } 451 452 int 453 smbfs_smb_create( 454 struct smbnode *dnp, 455 const char *name, 456 int nmlen, 457 int xattr, 458 uint32_t disp, 459 struct smb_cred *scrp, 460 smb_fh_t **fhpp) 461 { 462 struct smb_share *ssp = dnp->n_mount->smi_share; 463 // struct smb_vc *vcp = SSTOVC(ssp); 464 smb_fh_t *fhp = NULL; 465 uint32_t efa, rights; 466 int error; 467 468 error = smb_fh_create(ssp, &fhp); 469 if (error != 0) 470 goto out; 471 472 /* 473 * At present the only access we might need is to WRITE data, 474 * and that only if we are creating a "symlink". When/if the 475 * access needed gets more complex it should made a parameter 476 * and be set upstream. 477 */ 478 rights = SA_RIGHT_FILE_WRITE_DATA; 479 efa = SMB_EFA_NORMAL; 480 if (!xattr && name && *name == '.') 481 efa = SMB_EFA_HIDDEN; 482 error = smbfs_smb_ntcreatex(dnp, 483 name, nmlen, xattr, rights, efa, 484 NTCREATEX_SHARE_ACCESS_ALL, 485 disp, /* != NTCREATEX_DISP_OPEN */ 486 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE, 487 scrp, fhp, NULL, NULL); 488 if (error != 0) 489 goto out; 490 491 fhp->fh_rights = rights; 492 smb_fh_opened(fhp); 493 *fhpp = fhp; 494 fhp = NULL; 495 496 out: 497 if (fhp != NULL) 498 smb_fh_rele(fhp); 499 500 return (error); 501 } 502 503 int 504 smbfs_smb_rename(struct smbnode *sdnp, struct smbnode *np, 505 struct smbnode *tdnp, const char *tname, int tnlen, 506 smb_fh_t *fhp, struct smb_cred *scrp) 507 { 508 struct smb_share *ssp = np->n_mount->smi_share; 509 struct smb_vc *vcp = SSTOVC(ssp); 510 int err; 511 512 if (vcp->vc_flags & SMBV_SMB2) { 513 err = smbfs_smb2_rename(np, tdnp, tname, tnlen, 0, 514 &fhp->fh_fid2, scrp); 515 return (err); 516 } 517 518 /* 519 * SMB1 -- Want to use _t2rename if we can 520 * (rename in same dir and cap pass-through) 521 * Most SMB1 servers have cap pass-through. 522 */ 523 if (sdnp == tdnp && 524 (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) != 0) { 525 err = smbfs_smb1_t2rename(np, tname, tnlen, fhp->fh_fid1, scrp); 526 } else { 527 err = smbfs_smb1_oldrename(np, tdnp, tname, tnlen, scrp); 528 } 529 530 return (err); 531 } 532 533 int 534 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen, 535 struct smb_cred *scrp) 536 { 537 smb_fh_t tmp_fh; 538 struct smb_share *ssp = dnp->n_mount->smi_share; 539 uint32_t efa, rights; 540 int error; 541 542 /* 543 * Using a faked-up handle here to avoid the work of 544 * creating and destroying a real "conn obj". 545 */ 546 bzero(&tmp_fh, sizeof (tmp_fh)); 547 548 /* 549 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but 550 * just to be asking for something. The rights==0 case could 551 * easily be broken on some old or unusual servers. 552 */ 553 rights = SA_RIGHT_FILE_READ_DATA; 554 efa = SMB_EFA_NORMAL; 555 if (name && *name == '.') 556 efa |= SMB_EFA_HIDDEN; 557 error = smbfs_smb_ntcreatex(dnp, 558 name, nmlen, 0, /* xattr */ 559 rights, SMB_EFA_DIRECTORY, 560 NTCREATEX_SHARE_ACCESS_ALL, 561 NTCREATEX_DISP_CREATE, 562 NTCREATEX_OPTIONS_DIRECTORY, 563 scrp, &tmp_fh, NULL, NULL); 564 if (error == 0) { 565 (void) smb_smb_close(ssp, &tmp_fh, scrp); 566 } 567 568 return (error); 569 } 570 571 /* 572 * Protocol-level directory open 573 */ 574 int 575 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen, 576 int attr, struct smb_cred *scrp, 577 struct smbfs_fctx **ctxpp) 578 { 579 struct smb_share *ssp = dnp->n_mount->smi_share; 580 struct smb_vc *vcp = SSTOVC(ssp); 581 struct smbfs_fctx *ctx; 582 int error; 583 584 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 585 586 ctx->f_flags = SMBFS_RDD_FINDFIRST; 587 ctx->f_dnp = dnp; 588 ctx->f_scred = scrp; 589 ctx->f_ssp = ssp; 590 591 if (dnp->n_flag & N_XATTR) { 592 error = smbfs_xa_findopen(ctx, dnp, wild, wlen); 593 goto out; 594 } 595 596 if (vcp->vc_flags & SMBV_SMB2) { 597 error = smbfs_smb2_findopen(ctx, dnp, wild, wlen, attr); 598 } else { 599 error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr); 600 } 601 602 out: 603 ctx->f_scred = NULL; 604 if (error) { 605 kmem_free(ctx, sizeof (*ctx)); 606 } else { 607 *ctxpp = ctx; 608 } 609 610 return (error); 611 } 612 613 int 614 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp) 615 { 616 int error = 0; 617 uint16_t lim; 618 619 /* 620 * Note: "limit" (maxcount) needs to fit in a short! 621 */ 622 if (limit > 0xffff) 623 limit = 0xffff; 624 lim = (uint16_t)limit; 625 626 ctx->f_scred = scrp; 627 for (;;) { 628 bzero(&ctx->f_attr, sizeof (ctx->f_attr)); 629 switch (ctx->f_type) { 630 631 case ft_SMB2: 632 error = smbfs_smb2_findnext(ctx, lim); 633 break; 634 case ft_LM2: 635 error = smbfs_smb_findnextLM2(ctx, lim); 636 break; 637 case ft_XA: 638 error = smbfs_xa_findnext(ctx, lim); 639 break; 640 default: 641 ASSERT(0); 642 error = EINVAL; 643 break; 644 } 645 if (error) 646 break; 647 /* 648 * Skip "." or ".." - easy now that ctx->f_name 649 * has already been converted to utf-8 format. 650 */ 651 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || 652 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && 653 ctx->f_name[1] == '.')) 654 continue; 655 break; 656 } 657 ctx->f_scred = NULL; 658 if (error != 0) 659 return (error); 660 661 ctx->f_inum = smbfs_getino(ctx->f_dnp, 662 ctx->f_name, ctx->f_nmlen); 663 664 #ifdef DEBUG 665 SMBVDEBUG("findnext: (%s)\n", ctx->f_name); 666 #endif 667 668 return (error); 669 } 670 671 672 int 673 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp) 674 { 675 int error; 676 677 ctx->f_scred = scrp; 678 switch (ctx->f_type) { 679 case ft_SMB2: 680 error = smbfs_smb2_findclose(ctx); 681 break; 682 case ft_LM2: 683 error = smbfs_smb_findcloseLM2(ctx); 684 break; 685 case ft_XA: 686 error = smbfs_xa_findclose(ctx); 687 break; 688 default: 689 error = ENOSYS; 690 break; 691 } 692 ctx->f_scred = NULL; 693 if (ctx->f_rname) 694 kmem_free(ctx->f_rname, ctx->f_rnamelen); 695 if (ctx->f_firstnm) 696 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen); 697 kmem_free(ctx, sizeof (*ctx)); 698 return (error); 699 } 700 701 702 int 703 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, 704 struct smbfattr *fap, struct smb_cred *scrp) 705 { 706 struct smbfs_fctx *ctx; 707 int error, intr; 708 const char *name = (namep ? *namep : NULL); 709 int nmlen = (nmlenp ? *nmlenp : 0); 710 711 /* This is no longer called with a null dnp */ 712 ASSERT(dnp); 713 714 /* 715 * Should not get here with "" anymore. 716 */ 717 if (!name || !nmlen) { 718 DEBUG_ENTER("smbfs_smb_lookup: name is NULL"); 719 return (EINVAL); 720 } 721 722 /* 723 * Should not get here with "." or ".." anymore. 724 */ 725 if ((nmlen == 1 && name[0] == '.') || 726 (nmlen == 2 && name[0] == '.' && name[1] == '.')) { 727 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'"); 728 return (EINVAL); 729 } 730 731 /* 732 * Shared lock for n_fid use (smb_flush). 733 */ 734 intr = dnp->n_mount->smi_flags & SMI_INT; 735 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr)) 736 return (EINTR); 737 738 error = smbfs_smb_findopen(dnp, name, nmlen, 739 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx); 740 if (error) 741 goto out; 742 ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 743 error = smbfs_smb_findnext(ctx, 1, scrp); 744 if (error == 0) { 745 *fap = ctx->f_attr; 746 /* 747 * Solaris smbfattr doesn't have fa_ino, 748 * and we don't allow name==NULL in this 749 * function anymore. 750 */ 751 if (namep) 752 *namep = (const char *)smbfs_name_alloc( 753 ctx->f_name, ctx->f_nmlen); 754 if (nmlenp) 755 *nmlenp = ctx->f_nmlen; 756 } 757 (void) smbfs_smb_findclose(ctx, scrp); 758 759 out: 760 smbfs_rw_exit(&dnp->r_lkserlock); 761 return (error); 762 } 763 764 /* 765 * OTW function to Get a security descriptor (SD). 766 * 767 * Note: On success, this fills in mdp->md_top, 768 * which the caller should free. 769 */ 770 int 771 smbfs_smb_getsec(struct smb_share *ssp, smb_fh_t *fhp, 772 uint32_t selector, mblk_t **res, uint32_t *reslen, 773 struct smb_cred *scrp) 774 { 775 struct smb_vc *vcp = SSTOVC(ssp); 776 int error, len; 777 778 *res = NULL; 779 780 if (vcp->vc_flags & SMBV_SMB2) { 781 error = smbfs_smb2_getsec(ssp, &fhp->fh_fid2, 782 selector, res, reslen, scrp); 783 } else { 784 error = smbfs_smb1_getsec(ssp, fhp->fh_fid1, 785 selector, res, reslen, scrp); 786 } 787 788 /* 789 * get the data part. 790 */ 791 if (*res == NULL) { 792 error = EBADRPC; 793 goto done; 794 } 795 796 /* 797 * If message length is < returned SD_length, 798 * correct *reslen (reduce it). It greater, 799 * just ignore the extra data. 800 */ 801 len = m_fixhdr(*res); 802 if (len < *reslen) 803 *reslen = len; 804 805 done: 806 if (error == 0 && *res == NULL) { 807 ASSERT(*res); 808 error = EBADRPC; 809 } 810 811 return (error); 812 } 813 814 /* 815 * OTW function to Set a security descriptor (SD). 816 * Caller data are carried in an mbchain_t. 817 * 818 * Note: This normally consumes mbp->mb_top, and clears 819 * that pointer when it does. 820 */ 821 int 822 smbfs_smb_setsec(struct smb_share *ssp, smb_fh_t *fhp, 823 uint32_t selector, mblk_t **mp, 824 struct smb_cred *scrp) 825 { 826 struct smb_vc *vcp = SSTOVC(ssp); 827 int error; 828 829 if (vcp->vc_flags & SMBV_SMB2) { 830 error = smbfs_smb2_setsec(ssp, &fhp->fh_fid2, 831 selector, mp, scrp); 832 } else { 833 error = smbfs_smb1_setsec(ssp, fhp->fh_fid1, 834 selector, mp, scrp); 835 } 836 837 return (error); 838 } 839