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 2019 Nexenta by DDN, 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 mb_put_uint32le(mbp, 0); /* reserved */ 269 270 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 271 error = smbfs_smb2_setfattr(ssp, &fhp->fh_fid2, mbp, scrp); 272 } else { 273 error = smbfs_smb1_setfattr(ssp, fhp->fh_fid1, mbp, scrp); 274 } 275 276 return (error); 277 } 278 279 int 280 smbfs_smb_flush(struct smb_share *ssp, smb_fh_t *fhp, 281 struct smb_cred *scrp) 282 { 283 int error; 284 285 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 286 error = smbfs_smb2_flush(ssp, &fhp->fh_fid2, scrp); 287 } else { 288 error = smbfs_smb1_flush(ssp, fhp->fh_fid1, scrp); 289 } 290 return (error); 291 } 292 293 /* 294 * Modern create/open of file or directory. 295 * On success, fills in fhp->fh_fid* and fhp->fh_rights 296 */ 297 int 298 smbfs_smb_ntcreatex( 299 struct smbnode *np, 300 const char *name, 301 int nmlen, 302 int xattr, /* is named stream? */ 303 uint32_t req_acc, /* requested access */ 304 uint32_t efa, /* ext. file attrs (DOS attr +) */ 305 uint32_t share_acc, 306 uint32_t disp, /* open disposition */ 307 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 308 struct smb_cred *scrp, 309 smb_fh_t *fhp, /* pre-made file handle to fill in */ 310 uint32_t *cr_act_p, /* optional returned create action */ 311 struct smbfattr *fap) /* optional returned attributes */ 312 { 313 struct mbchain name_mb; 314 struct smb_share *ssp = np->n_mount->smi_share; 315 int err; 316 317 mb_init(&name_mb); 318 319 if (name == NULL) 320 nmlen = 0; 321 err = smbfs_fullpath(&name_mb, SSTOVC(ssp), 322 np, name, nmlen, xattr ? ':' : '\\'); 323 if (err) 324 goto out; 325 326 err = smb_smb_ntcreate(ssp, &name_mb, 327 0, /* NTCREATEX_FLAGS... */ 328 req_acc, efa, share_acc, disp, createopt, 329 NTCREATEX_IMPERSONATION_IMPERSONATION, 330 scrp, fhp, cr_act_p, fap); 331 332 out: 333 mb_done(&name_mb); 334 335 return (err); 336 } 337 338 /* 339 * Get a file handle with (at least) the specified rights. 340 * 341 * We'll try to borrow the node ->n_fid if we can. When we 342 * borrow n_fid, just take a hold on the smb_fh_t, and don't 343 * bump n_fidrefs as that tracks VFS-level opens. Similarly 344 * in _tmpclose we just release the smb_fh_t, not n_fidrefs. 345 */ 346 int 347 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp, 348 smb_fh_t **fhpp) 349 { 350 struct smb_share *ssp = np->n_mount->smi_share; 351 smb_fh_t *fhp = NULL; 352 int error; 353 354 /* Can we re-use n_fid? or must we open anew? */ 355 mutex_enter(&np->r_statelock); 356 if (np->n_fidrefs > 0 && 357 (fhp = np->n_fid) != NULL && 358 fhp->fh_vcgenid == ssp->ss_vcgenid && 359 (fhp->fh_rights & rights) == rights) { 360 smb_fh_hold(fhp); 361 *fhpp = fhp; 362 mutex_exit(&np->r_statelock); 363 return (0); 364 } 365 mutex_exit(&np->r_statelock); 366 367 error = smb_fh_create(ssp, &fhp); 368 if (error != 0) 369 goto out; 370 371 /* re-open an existing file. */ 372 error = smbfs_smb_ntcreatex(np, 373 NULL, 0, 0, /* name nmlen xattr */ 374 rights, SMB_EFA_NORMAL, 375 NTCREATEX_SHARE_ACCESS_ALL, 376 NTCREATEX_DISP_OPEN, 377 0, /* create options */ 378 scrp, fhp, 379 NULL, NULL); /* cr_act_p fa_p */ 380 if (error != 0) 381 goto out; 382 383 fhp->fh_rights = rights; 384 smb_fh_opened(fhp); 385 *fhpp = fhp; 386 fhp = NULL; 387 388 out: 389 if (fhp != NULL) 390 smb_fh_rele(fhp); 391 392 return (error); 393 } 394 395 /* ARGSUSED */ 396 void 397 smbfs_smb_tmpclose(struct smbnode *np, smb_fh_t *fhp) 398 { 399 smb_fh_rele(fhp); 400 } 401 402 int 403 smbfs_smb_open( 404 struct smbnode *np, 405 const char *name, 406 int nmlen, 407 int xattr, 408 uint32_t rights, 409 struct smb_cred *scrp, 410 smb_fh_t **fhpp, 411 smbfattr_t *fap) 412 { 413 struct smb_share *ssp = np->n_mount->smi_share; 414 // struct smb_vc *vcp = SSTOVC(ssp); 415 smb_fh_t *fhp = NULL; 416 int error; 417 418 error = smb_fh_create(ssp, &fhp); 419 if (error != 0) 420 goto out; 421 422 /* open an existing file */ 423 error = smbfs_smb_ntcreatex(np, 424 name, nmlen, xattr, 425 rights, SMB_EFA_NORMAL, 426 NTCREATEX_SHARE_ACCESS_ALL, 427 NTCREATEX_DISP_OPEN, 428 0, /* create options */ 429 scrp, fhp, NULL, fap); 430 if (error != 0) 431 goto out; 432 433 fhp->fh_rights = rights; 434 smb_fh_opened(fhp); 435 *fhpp = fhp; 436 fhp = NULL; 437 438 out: 439 if (fhp != NULL) 440 smb_fh_rele(fhp); 441 442 return (0); 443 } 444 445 void 446 smbfs_smb_close(smb_fh_t *fhp) 447 { 448 449 smb_fh_close(fhp); 450 smb_fh_rele(fhp); 451 } 452 453 int 454 smbfs_smb_create( 455 struct smbnode *dnp, 456 const char *name, 457 int nmlen, 458 int xattr, 459 uint32_t disp, 460 struct smb_cred *scrp, 461 smb_fh_t **fhpp) 462 { 463 struct smb_share *ssp = dnp->n_mount->smi_share; 464 // struct smb_vc *vcp = SSTOVC(ssp); 465 smb_fh_t *fhp = NULL; 466 uint32_t efa, rights; 467 int error; 468 469 error = smb_fh_create(ssp, &fhp); 470 if (error != 0) 471 goto out; 472 473 /* 474 * At present the only access we might need is to WRITE data, 475 * and that only if we are creating a "symlink". When/if the 476 * access needed gets more complex it should made a parameter 477 * and be set upstream. 478 */ 479 rights = SA_RIGHT_FILE_WRITE_DATA; 480 efa = SMB_EFA_NORMAL; 481 if (!xattr && name && *name == '.') 482 efa = SMB_EFA_HIDDEN; 483 error = smbfs_smb_ntcreatex(dnp, 484 name, nmlen, xattr, rights, efa, 485 NTCREATEX_SHARE_ACCESS_ALL, 486 disp, /* != NTCREATEX_DISP_OPEN */ 487 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE, 488 scrp, fhp, NULL, NULL); 489 if (error != 0) 490 goto out; 491 492 fhp->fh_rights = rights; 493 smb_fh_opened(fhp); 494 *fhpp = fhp; 495 fhp = NULL; 496 497 out: 498 if (fhp != NULL) 499 smb_fh_rele(fhp); 500 501 return (error); 502 } 503 504 int 505 smbfs_smb_rename(struct smbnode *sdnp, struct smbnode *np, 506 struct smbnode *tdnp, const char *tname, int tnlen, 507 smb_fh_t *fhp, struct smb_cred *scrp) 508 { 509 struct smb_share *ssp = np->n_mount->smi_share; 510 struct smb_vc *vcp = SSTOVC(ssp); 511 int err; 512 513 if (vcp->vc_flags & SMBV_SMB2) { 514 err = smbfs_smb2_rename(np, tdnp, tname, tnlen, 0, 515 &fhp->fh_fid2, scrp); 516 return (err); 517 } 518 519 /* 520 * SMB1 -- Want to use _t2rename if we can 521 * (rename in same dir and cap pass-through) 522 * Most SMB1 servers have cap pass-through. 523 */ 524 if (sdnp == tdnp && 525 (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) != 0) { 526 err = smbfs_smb1_t2rename(np, tname, tnlen, fhp->fh_fid1, scrp); 527 } else { 528 err = smbfs_smb1_oldrename(np, tdnp, tname, tnlen, scrp); 529 } 530 531 return (err); 532 } 533 534 int 535 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen, 536 struct smb_cred *scrp) 537 { 538 smb_fh_t tmp_fh; 539 struct smb_share *ssp = dnp->n_mount->smi_share; 540 uint32_t efa, rights; 541 int error; 542 543 /* 544 * Using a faked-up handle here to avoid the work of 545 * creating and destroying a real "conn obj". 546 */ 547 bzero(&tmp_fh, sizeof (tmp_fh)); 548 549 /* 550 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but 551 * just to be asking for something. The rights==0 case could 552 * easily be broken on some old or unusual servers. 553 */ 554 rights = SA_RIGHT_FILE_READ_DATA; 555 efa = SMB_EFA_NORMAL; 556 if (name && *name == '.') 557 efa |= SMB_EFA_HIDDEN; 558 error = smbfs_smb_ntcreatex(dnp, 559 name, nmlen, 0, /* xattr */ 560 rights, SMB_EFA_DIRECTORY, 561 NTCREATEX_SHARE_ACCESS_ALL, 562 NTCREATEX_DISP_CREATE, 563 NTCREATEX_OPTIONS_DIRECTORY, 564 scrp, &tmp_fh, NULL, NULL); 565 if (error == 0) { 566 (void) smb_smb_close(ssp, &tmp_fh, scrp); 567 } 568 569 return (error); 570 } 571 572 /* 573 * Protocol-level directory open 574 */ 575 int 576 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen, 577 int attr, struct smb_cred *scrp, 578 struct smbfs_fctx **ctxpp) 579 { 580 struct smb_share *ssp = dnp->n_mount->smi_share; 581 struct smb_vc *vcp = SSTOVC(ssp); 582 struct smbfs_fctx *ctx; 583 int error; 584 585 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 586 587 ctx->f_flags = SMBFS_RDD_FINDFIRST; 588 ctx->f_dnp = dnp; 589 ctx->f_scred = scrp; 590 ctx->f_ssp = ssp; 591 592 if (dnp->n_flag & N_XATTR) { 593 error = smbfs_xa_findopen(ctx, dnp, wild, wlen); 594 goto out; 595 } 596 597 if (vcp->vc_flags & SMBV_SMB2) { 598 error = smbfs_smb2_findopen(ctx, dnp, wild, wlen, attr); 599 } else { 600 error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr); 601 } 602 603 out: 604 ctx->f_scred = NULL; 605 if (error) { 606 kmem_free(ctx, sizeof (*ctx)); 607 } else { 608 *ctxpp = ctx; 609 } 610 611 return (error); 612 } 613 614 int 615 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp) 616 { 617 int error = 0; 618 uint16_t lim; 619 620 /* 621 * Note: "limit" (maxcount) needs to fit in a short! 622 */ 623 if (limit > 0xffff) 624 limit = 0xffff; 625 lim = (uint16_t)limit; 626 627 ctx->f_scred = scrp; 628 for (;;) { 629 bzero(&ctx->f_attr, sizeof (ctx->f_attr)); 630 switch (ctx->f_type) { 631 632 case ft_SMB2: 633 error = smbfs_smb2_findnext(ctx, lim); 634 break; 635 case ft_LM2: 636 error = smbfs_smb_findnextLM2(ctx, lim); 637 break; 638 case ft_XA: 639 error = smbfs_xa_findnext(ctx, lim); 640 break; 641 default: 642 ASSERT(0); 643 error = EINVAL; 644 break; 645 } 646 if (error) 647 break; 648 /* 649 * Skip "." or ".." - easy now that ctx->f_name 650 * has already been converted to utf-8 format. 651 */ 652 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || 653 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && 654 ctx->f_name[1] == '.')) 655 continue; 656 break; 657 } 658 ctx->f_scred = NULL; 659 if (error != 0) 660 return (error); 661 662 ctx->f_inum = smbfs_getino(ctx->f_dnp, 663 ctx->f_name, ctx->f_nmlen); 664 665 #ifdef DEBUG 666 SMBVDEBUG("findnext: (%s)\n", ctx->f_name); 667 #endif 668 669 return (error); 670 } 671 672 673 int 674 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp) 675 { 676 int error; 677 678 ctx->f_scred = scrp; 679 switch (ctx->f_type) { 680 case ft_SMB2: 681 error = smbfs_smb2_findclose(ctx); 682 break; 683 case ft_LM2: 684 error = smbfs_smb_findcloseLM2(ctx); 685 break; 686 case ft_XA: 687 error = smbfs_xa_findclose(ctx); 688 break; 689 default: 690 error = ENOSYS; 691 break; 692 } 693 ctx->f_scred = NULL; 694 if (ctx->f_rname) 695 kmem_free(ctx->f_rname, ctx->f_rnamelen); 696 if (ctx->f_firstnm) 697 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen); 698 kmem_free(ctx, sizeof (*ctx)); 699 return (error); 700 } 701 702 703 int 704 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, 705 struct smbfattr *fap, struct smb_cred *scrp) 706 { 707 struct smbfs_fctx *ctx; 708 int error, intr; 709 const char *name = (namep ? *namep : NULL); 710 int nmlen = (nmlenp ? *nmlenp : 0); 711 712 /* This is no longer called with a null dnp */ 713 ASSERT(dnp); 714 715 /* 716 * Should not get here with "" anymore. 717 */ 718 if (!name || !nmlen) { 719 DEBUG_ENTER("smbfs_smb_lookup: name is NULL"); 720 return (EINVAL); 721 } 722 723 /* 724 * Should not get here with "." or ".." anymore. 725 */ 726 if ((nmlen == 1 && name[0] == '.') || 727 (nmlen == 2 && name[0] == '.' && name[1] == '.')) { 728 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'"); 729 return (EINVAL); 730 } 731 732 /* 733 * Shared lock for n_fid use (smb_flush). 734 */ 735 intr = dnp->n_mount->smi_flags & SMI_INT; 736 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr)) 737 return (EINTR); 738 739 error = smbfs_smb_findopen(dnp, name, nmlen, 740 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx); 741 if (error) 742 goto out; 743 ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 744 error = smbfs_smb_findnext(ctx, 1, scrp); 745 if (error == 0) { 746 *fap = ctx->f_attr; 747 /* 748 * Solaris smbfattr doesn't have fa_ino, 749 * and we don't allow name==NULL in this 750 * function anymore. 751 */ 752 if (namep) 753 *namep = (const char *)smbfs_name_alloc( 754 ctx->f_name, ctx->f_nmlen); 755 if (nmlenp) 756 *nmlenp = ctx->f_nmlen; 757 } 758 (void) smbfs_smb_findclose(ctx, scrp); 759 760 out: 761 smbfs_rw_exit(&dnp->r_lkserlock); 762 return (error); 763 } 764 765 /* 766 * OTW function to Get a security descriptor (SD). 767 * 768 * Note: On success, this fills in mdp->md_top, 769 * which the caller should free. 770 */ 771 int 772 smbfs_smb_getsec(struct smb_share *ssp, smb_fh_t *fhp, 773 uint32_t selector, mblk_t **res, uint32_t *reslen, 774 struct smb_cred *scrp) 775 { 776 struct smb_vc *vcp = SSTOVC(ssp); 777 int error, len; 778 779 *res = NULL; 780 781 if (vcp->vc_flags & SMBV_SMB2) { 782 error = smbfs_smb2_getsec(ssp, &fhp->fh_fid2, 783 selector, res, reslen, scrp); 784 } else { 785 error = smbfs_smb1_getsec(ssp, fhp->fh_fid1, 786 selector, res, reslen, scrp); 787 } 788 789 /* 790 * get the data part. 791 */ 792 if (*res == NULL) { 793 error = EBADRPC; 794 goto done; 795 } 796 797 /* 798 * If message length is < returned SD_length, 799 * correct *reslen (reduce it). It greater, 800 * just ignore the extra data. 801 */ 802 len = m_fixhdr(*res); 803 if (len < *reslen) 804 *reslen = len; 805 806 done: 807 if (error == 0 && *res == NULL) { 808 ASSERT(*res); 809 error = EBADRPC; 810 } 811 812 return (error); 813 } 814 815 /* 816 * OTW function to Set a security descriptor (SD). 817 * Caller data are carried in an mbchain_t. 818 * 819 * Note: This normally consumes mbp->mb_top, and clears 820 * that pointer when it does. 821 */ 822 int 823 smbfs_smb_setsec(struct smb_share *ssp, smb_fh_t *fhp, 824 uint32_t selector, mblk_t **mp, 825 struct smb_cred *scrp) 826 { 827 struct smb_vc *vcp = SSTOVC(ssp); 828 int error; 829 830 if (vcp->vc_flags & SMBV_SMB2) { 831 error = smbfs_smb2_setsec(ssp, &fhp->fh_fid2, 832 selector, mp, scrp); 833 } else { 834 error = smbfs_smb1_setsec(ssp, fhp->fh_fid1, 835 selector, mp, scrp); 836 } 837 838 return (error); 839 } 840