Print this page
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4458 Incorrect directory listing response for non-UNICODE clients
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-4540 SMB server declines EA support incorrectly
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-4053 Customer DIR command hangs with smb2 enabled
NEX-4080 SMB_ODIR_FLAG_WILDCARDS can be incorrectly inherited
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #10733 Windows 7 directory listing keeps restarting (fix lint)
re #10733 Windows 7 directory listing keeps restarting

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   *
  25      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       25 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  26   26   */
  27   27  
  28   28  
  29   29  /*
  30   30   * This module provides functions for TRANS2_FIND_FIRST2 and
  31   31   * TRANS2_FIND_NEXT2 requests. The requests allow the client to search
  32   32   * for the file(s) which match the file specification.  The search is
  33   33   * started with TRANS2_FIND_FIRST2 and can be continued if necessary with
  34   34   * TRANS2_FIND_NEXT2. There are numerous levels of information which may be
  35   35   * obtained for the returned files, the desired level is specified in the
↓ open down ↓ 170 lines elided ↑ open up ↑
 206  206  
 207  207  #include <smbsrv/smb_kproto.h>
 208  208  #include <smbsrv/msgbuf.h>
 209  209  #include <smbsrv/smb_fsops.h>
 210  210  
 211  211  /*
 212  212   * Args (and other state) that we carry around among the
 213  213   * various functions involved in FindFirst, FindNext.
 214  214   */
 215  215  typedef struct smb_find_args {
 216      -        uint32_t fa_maxdata;
      216 +        uint32_t fa_fixedsize;
 217  217          uint16_t fa_infolev;
 218  218          uint16_t fa_maxcount;
 219  219          uint16_t fa_fflag;
 220  220          uint16_t fa_eos;        /* End Of Search */
 221  221          uint16_t fa_lno;        /* Last Name Offset */
 222  222          uint32_t fa_lastkey;    /* Last resume key */
 223  223          char fa_lastname[MAXNAMELEN]; /* and name */
 224  224  } smb_find_args_t;
 225  225  
 226  226  static int smb_trans2_find_entries(smb_request_t *, smb_xa_t *,
 227  227      smb_odir_t *, smb_find_args_t *);
 228      -static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t);
      228 +static int smb_trans2_find_get_fixedsize(smb_request_t *, uint16_t, uint16_t);
 229  229  static int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *,
 230  230      smb_fileinfo_t *, smb_find_args_t *);
 231  231  
 232  232  /*
 233  233   * Tunable parameter to limit the maximum
 234  234   * number of entries to be returned.
 235  235   */
 236  236  uint16_t smb_trans2_find_max = 128;
 237  237  
 238  238  /*
↓ open down ↓ 74 lines elided ↑ open up ↑
 313  313                  smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
 314  314                      ERRDOS, ERROR_INVALID_NAME);
 315  315                  return (SDRC_ERROR);
 316  316          }
 317  317  
 318  318          if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT) {
 319  319                  sr->user_cr = smb_user_getprivcred(sr->uid_user);
 320  320                  odir_flags = SMB_ODIR_OPENF_BACKUP_INTENT;
 321  321          }
 322  322  
 323      -        args.fa_maxdata =
 324      -            smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag);
 325      -        if (args.fa_maxdata == 0)
      323 +        args.fa_fixedsize =
      324 +            smb_trans2_find_get_fixedsize(sr, args.fa_infolev, args.fa_fflag);
      325 +        if (args.fa_fixedsize == 0)
 326  326                  return (SDRC_ERROR);
 327  327  
 328  328          status = smb_odir_openpath(sr, pn->pn_path, sattr, odir_flags, &od);
 329  329          if (status != 0) {
 330  330                  smbsr_error(sr, status, 0, 0);
 331  331                  return (SDRC_ERROR);
 332  332          }
 333  333          if (od == NULL)
 334  334                  return (SDRC_ERROR);
 335  335  
↓ open down ↓ 1 lines elided ↑ open up ↑
 337  337  
 338  338          if (count == -1) {
 339  339                  smb_odir_close(od);
 340  340                  smb_odir_release(od);
 341  341                  return (SDRC_ERROR);
 342  342          }
 343  343  
 344  344          if (count == 0) {
 345  345                  smb_odir_close(od);
 346  346                  smb_odir_release(od);
 347      -                smbsr_errno(sr, ENOENT);
      347 +                smbsr_status(sr, NT_STATUS_NO_SUCH_FILE,
      348 +                    ERRDOS, ERROR_FILE_NOT_FOUND);
 348  349                  return (SDRC_ERROR);
 349  350          }
 350  351  
 351  352          if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) ||
 352  353              (args.fa_eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
 353  354                  smb_odir_close(od);
 354  355          } /* else leave odir open for trans2_find_next2 */
 355  356  
 356  357          (void) smb_mbc_encodef(&xa->rep_param_mb, "wwwww",
 357  358              od->d_odid, /* Search ID */
↓ open down ↓ 90 lines elided ↑ open up ↑
 448  449          if (smb_mbc_decodef(&xa->req_param_mb, "%wwwlwu", sr,
 449  450              &odid, &args.fa_maxcount, &args.fa_infolev,
 450  451              &odir_resume.or_cookie, &args.fa_fflag,
 451  452              &odir_resume.or_fname) != 0) {
 452  453                  return (SDRC_ERROR);
 453  454          }
 454  455  
 455  456          if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT)
 456  457                  sr->user_cr = smb_user_getprivcred(sr->uid_user);
 457  458  
 458      -        args.fa_maxdata =
 459      -            smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag);
 460      -        if (args.fa_maxdata == 0)
      459 +        args.fa_fixedsize =
      460 +            smb_trans2_find_get_fixedsize(sr, args.fa_infolev, args.fa_fflag);
      461 +        if (args.fa_fixedsize == 0)
 461  462                  return (SDRC_ERROR);
 462  463  
 463  464          od = smb_tree_lookup_odir(sr, odid);
 464  465          if (od == NULL) {
 465  466                  smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 466  467                      ERRDOS, ERROR_INVALID_HANDLE);
 467  468                  return (SDRC_ERROR);
 468  469          }
 469  470  
 470  471          /*
↓ open down ↓ 58 lines elided ↑ open up ↑
 529  530   *      -1 - error
 530  531   */
 531  532  static int
 532  533  smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
 533  534      smb_find_args_t *args)
 534  535  {
 535  536          smb_fileinfo_t  fileinfo;
 536  537          smb_odir_resume_t odir_resume;
 537  538          uint16_t        count, maxcount;
 538  539          int             rc = -1;
      540 +        int             LastEntryOffset = 0;
 539  541          boolean_t       need_rewind = B_FALSE;
 540  542  
      543 +        /*
      544 +         * EAs are not current supported, so a search for level
      545 +         * SMB_INFO_QUERY_EAS_FROM_LIST should always return an
      546 +         * empty list.  Returning zero for this case gives the
      547 +         * client an empty response, which is better than an
      548 +         * NT_STATUS_INVALID_LEVEL return (and test failures).
      549 +         *
      550 +         * If and when we do support EAs, this level will modify
      551 +         * the search here, and then return results just like
      552 +         * SMB_INFO_QUERY_EA_SIZE, but only including files
      553 +         * that have an EA in the provided list.
      554 +         */
      555 +        if (args->fa_infolev == SMB_INFO_QUERY_EAS_FROM_LIST)
      556 +                return (0);
      557 +
 541  558          if ((maxcount = args->fa_maxcount) == 0)
 542  559                  maxcount = 1;
 543  560  
 544  561          if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max))
 545  562                  maxcount = smb_trans2_find_max;
 546  563  
 547  564          count = 0;
 548  565          while (count < maxcount) {
 549  566                  rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &args->fa_eos);
 550  567                  if (rc != 0 || args->fa_eos != 0)
 551  568                          break;
 552  569  
      570 +                LastEntryOffset = xa->rep_data_mb.chain_offset;
 553  571                  rc = smb_trans2_find_mbc_encode(sr, xa, &fileinfo, args);
 554  572                  if (rc == -1)
 555  573                          return (-1); /* fatal encoding error */
 556  574                  if (rc == 1) {
 557  575                          need_rewind = B_TRUE;
 558  576                          break; /* output space exhausted */
 559  577                  }
 560  578  
 561  579                  /*
 562  580                   * Save the info about the last file returned.
 563  581                   */
 564  582                  args->fa_lastkey = fileinfo.fi_cookie;
 565  583                  bcopy(fileinfo.fi_name, args->fa_lastname, MAXNAMELEN);
 566  584  
 567  585                  ++count;
 568  586          }
 569  587          if (args->fa_eos != 0 && rc == ENOENT)
 570  588                  rc = 0;
 571  589  
      590 +        /*
      591 +         * All but the ancient info levels start with NextEntryOffset.
      592 +         * That's supposed to be zero in the last entry returned.
      593 +         */
      594 +        if (args->fa_infolev >= SMB_FIND_FILE_DIRECTORY_INFO) {
      595 +                (void) smb_mbc_poke(&xa->rep_data_mb,
      596 +                    LastEntryOffset, "l", 0);
      597 +        }
      598 +
 572  599          /* save the last cookie returned to client */
 573  600          if (count != 0)
 574  601                  smb_odir_save_fname(od, args->fa_lastkey, args->fa_lastname);
 575  602  
 576  603          /*
 577  604           * If all retrieved entries have been successfully encoded
 578  605           * and eos has not already been detected, check if there are
 579  606           * any more entries. eos will be set if there are no more.
 580  607           */
 581  608          if ((rc == 0) && (args->fa_eos == 0)) {
↓ open down ↓ 17 lines elided ↑ open up ↑
 599  626                  bzero(&odir_resume, sizeof (odir_resume));
 600  627                  odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
 601  628                  odir_resume.or_cookie = args->fa_lastkey;
 602  629                  smb_odir_resume_at(od, &odir_resume);
 603  630          }
 604  631  
 605  632          return (count);
 606  633  }
 607  634  
 608  635  /*
 609      - * smb_trans2_find_get_maxdata
      636 + * smb_trans2_find_get_fixedsize
 610  637   *
 611      - * Calculate the minimum response space required for the specified
 612      - * information level.
      638 + * Calculate the sizeof the fixed part of the response for the
      639 + * specified information level.
 613  640   *
 614      - * A non-zero return value provides the minimum space required.
      641 + * A non-zero return value provides the fixed size.
 615  642   * A return value of zero indicates an unknown information level.
 616  643   */
 617  644  static int
 618      -smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag)
      645 +smb_trans2_find_get_fixedsize(smb_request_t *sr, uint16_t infolev,
      646 +        uint16_t fflag)
 619  647  {
 620      -        int maxdata;
      648 +        int maxdata = 0;
 621  649  
 622      -        maxdata = smb_ascii_or_unicode_null_len(sr);
 623      -
 624  650          switch (infolev) {
 625  651          case SMB_INFO_STANDARD :
 626  652                  if (fflag & SMB_FIND_RETURN_RESUME_KEYS)
 627  653                          maxdata += sizeof (int32_t);
 628  654                  maxdata += 2 + 2 + 2 + 4 + 4 + 2 + 1;
 629  655                  break;
 630  656  
 631  657          case SMB_INFO_QUERY_EA_SIZE:
      658 +        case SMB_INFO_QUERY_EAS_FROM_LIST:
 632  659                  if (fflag & SMB_FIND_RETURN_RESUME_KEYS)
 633  660                          maxdata += sizeof (int32_t);
 634  661                  maxdata += 2 + 2 + 2 + 4 + 4 + 2 + 4 + 1;
 635  662                  break;
 636  663  
 637  664          case SMB_FIND_FILE_DIRECTORY_INFO:
 638  665                  maxdata += 4 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4;
 639  666                  break;
 640  667  
 641  668          case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
↓ open down ↓ 71 lines elided ↑ open up ↑
 713  740  smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
 714  741      smb_fileinfo_t *fileinfo, smb_find_args_t *args)
 715  742  {
 716  743          int             namelen, shortlen;
 717  744          uint32_t        next_entry_offset;
 718  745          uint32_t        dsize32, asize32;
 719  746          uint32_t        mb_flags = 0;
 720  747          uint32_t        resume_key;
 721  748          char            buf83[26];
 722  749          smb_msgbuf_t    mb;
      750 +        int             pad = 0;
 723  751  
 724  752          namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name);
 725  753          if (namelen == -1)
 726  754                  return (-1);
 727  755  
 728      -        /*
 729      -         * If ascii the filename length returned to the client should
 730      -         * include the null terminator for levels except STANDARD and
 731      -         * EASIZE.
 732      -         */
 733      -        if (!(sr->smb_flg2 & SMB_FLAGS2_UNICODE)) {
 734      -                if ((args->fa_infolev != SMB_INFO_STANDARD) &&
 735      -                    (args->fa_infolev != SMB_INFO_QUERY_EA_SIZE))
      756 +        if (args->fa_infolev < SMB_FIND_FILE_DIRECTORY_INFO) {
      757 +                /*
      758 +                 * Ancient info levels don't have a NextEntryOffset
      759 +                 * field, so there's no padding for alignment.
      760 +                 * The client expects a null after the file name,
      761 +                 * and then the next entry.  The namelength field
      762 +                 * never includes the null for these old levels.
      763 +                 * Using the pad value to write the null because
      764 +                 * we don't want to add that to namelen.
      765 +                 * [MS-CIFS] sec. 2.8.1.{1-3}
      766 +                 */
      767 +                if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
      768 +                        pad = 2; /* Unicode null */
      769 +                else
      770 +                        pad = 1; /* ascii null */
      771 +                next_entry_offset = args->fa_fixedsize + namelen + pad;
      772 +                if (!MBC_ROOM_FOR(&xa->rep_data_mb, next_entry_offset))
      773 +                        return (1);
      774 +        } else {
      775 +                /*
      776 +                 * Later info levels: The file name is written WITH
      777 +                 * null termination, and the size of that null _is_
      778 +                 * included in the namelen field.  There may also
      779 +                 * be padding, and we pad to align(4) like Windows.
      780 +                 * Don't include the padding in the "room for" test
      781 +                 * because we want to ignore any error writing the
      782 +                 * pad bytes after the last element.
      783 +                 */
      784 +                if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
      785 +                        namelen += 2;
      786 +                else
 736  787                          namelen += 1;
      788 +                next_entry_offset = args->fa_fixedsize + namelen;
      789 +                if (!MBC_ROOM_FOR(&xa->rep_data_mb, next_entry_offset))
      790 +                        return (1);
      791 +                if ((next_entry_offset & 3) != 0) {
      792 +                        pad = 4 - (next_entry_offset & 3);
      793 +                        next_entry_offset += pad;
      794 +                }
 737  795          }
 738  796  
 739      -        next_entry_offset = args->fa_maxdata + namelen;
 740      -
 741      -        if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
 742      -                return (1);
 743      -
 744  797          mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0;
 745  798          dsize32 = (fileinfo->fi_size > UINT_MAX) ?
 746  799              UINT_MAX : (uint32_t)fileinfo->fi_size;
 747  800          asize32 = (fileinfo->fi_alloc_size > UINT_MAX) ?
 748  801              UINT_MAX : (uint32_t)fileinfo->fi_alloc_size;
 749  802  
 750  803          resume_key = fileinfo->fi_cookie;
 751  804          if (smbd_use_resume_keys == 0)
 752  805                  resume_key = 0;
 753  806  
↓ open down ↓ 13 lines elided ↑ open up ↑
 767  820                      smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
 768  821                      smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
 769  822                      smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
 770  823                      dsize32,
 771  824                      asize32,
 772  825                      fileinfo->fi_dosattr,
 773  826                      namelen);
 774  827                  break;
 775  828  
 776  829          case SMB_INFO_QUERY_EA_SIZE:
      830 +        case SMB_INFO_QUERY_EAS_FROM_LIST:
 777  831                  if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
 778  832                          (void) smb_mbc_encodef(&xa->rep_data_mb, "l",
 779  833                              resume_key);
 780  834  
 781  835                  (void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb", sr,
 782  836                      smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
 783  837                      smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
 784  838                      smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
 785  839                      dsize32,
 786  840                      asize32,
↓ open down ↓ 127 lines elided ↑ open up ↑
 914  968           * need the offset in the trans2 data where this string
 915  969           * is placed, so save the message position now.  Note:
 916  970           * We also need to account for the alignment padding
 917  971           * that may precede the unicode string.
 918  972           */
 919  973          args->fa_lno = xa->rep_data_mb.chain_offset;
 920  974          if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0 &&
 921  975              (args->fa_lno & 1) != 0)
 922  976                  args->fa_lno++;
 923  977  
 924      -        (void) smb_mbc_encodef(&xa->rep_data_mb, "%u", sr,
 925      -            fileinfo->fi_name);
      978 +        (void) smb_mbc_encodef(&xa->rep_data_mb, "%#u", sr,
      979 +            namelen, fileinfo->fi_name);
 926  980  
      981 +        if (pad)
      982 +                (void) smb_mbc_encodef(&xa->rep_data_mb, "#.", pad);
      983 +
 927  984          return (0);
 928  985  }
 929  986  
 930  987  /*
 931  988   * Close a search started by a Trans2FindFirst2 request.
 932  989   */
 933  990  smb_sdrc_t
 934  991  smb_pre_find_close2(smb_request_t *sr)
 935  992  {
 936      -        DTRACE_SMB_1(op__FindClose2__start, smb_request_t *, sr);
      993 +        DTRACE_SMB_START(op__FindClose2, smb_request_t *, sr);
 937  994          return (SDRC_SUCCESS);
 938  995  }
 939  996  
 940  997  void
 941  998  smb_post_find_close2(smb_request_t *sr)
 942  999  {
 943      -        DTRACE_SMB_1(op__FindClose2__done, smb_request_t *, sr);
     1000 +        DTRACE_SMB_DONE(op__FindClose2, smb_request_t *, sr);
 944 1001  }
 945 1002  
 946 1003  smb_sdrc_t
 947 1004  smb_com_find_close2(smb_request_t *sr)
 948 1005  {
 949 1006          uint16_t        odid;
 950 1007          smb_odir_t      *od;
 951 1008  
 952 1009          if (smbsr_decode_vwv(sr, "w", &odid) != 0)
 953 1010                  return (SDRC_ERROR);
↓ open down ↓ 16 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX