Print this page
    
9500 HP scanner needs smaller SMB2 rwsize
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  14   14   */
  15   15  
  16   16  /*
  17   17   * Dispatch function for SMB2_NEGOTIATE
  18   18   */
  19   19  
  20   20  #include <smbsrv/smb2_kproto.h>
  21   21  #include <smbsrv/smb2.h>
  22   22  
  23   23  static int smb2_negotiate_common(smb_request_t *, uint16_t);
  24   24  
  25   25  uint32_t smb2srv_capabilities =
  26   26          SMB2_CAP_DFS |
  27   27          SMB2_CAP_LARGE_MTU;
  28   28  
  29   29  /*
  30   30   * These are not intended as customer tunables, but dev. & test folks
  31   31   * might want to adjust them (with caution).
  32   32   *
  33   33   * smb2_tcp_bufsize is the TCP buffer size, applied to the network socket
  34   34   * with setsockopt SO_SNDBUF, SO_RCVBUF.  These set the TCP window size.
  35   35   * This is also used as a "sanity limit" for internal send/reply message
  36   36   * allocations.  Note that with compounding SMB2 messages may contain
  37   37   * multiple requests/responses.  This size should be large enough for
  38   38   * at least a few SMB2 requests, and at least 2X smb2_max_rwsize.
  39   39   *
  40   40   * smb2_max_rwsize is what we put in the SMB2 negotiate response to tell
  41   41   * the client the largest read and write request size we'll support.
  42   42   * One megabyte is a compromise between efficiency on fast networks
  
    | 
      ↓ open down ↓ | 
    42 lines elided | 
    
      ↑ open up ↑ | 
  
  43   43   * and memory consumption (for the buffers) on the server side.
  44   44   *
  45   45   * smb2_max_trans is the largest "transact" send or receive, which is
  46   46   * used for directory listings and info set/get operations.
  47   47   */
  48   48  uint32_t smb2_tcp_bufsize = (1<<22);    /* 4MB */
  49   49  uint32_t smb2_max_rwsize = (1<<20);     /* 1MB */
  50   50  uint32_t smb2_max_trans  = (1<<16);     /* 64KB */
  51   51  
  52   52  /*
       53 + * With clients (e.g. HP scanners) that don't advertise SMB2_CAP_LARGE_MTU
       54 + * (including all clients using dialect < SMB 2.1), use a "conservative" value
       55 + * for max r/w size because some older clients misbehave with larger values.
       56 + * 64KB is recommended in the [MS-SMB2] spec.  (3.3.5.3.1 SMB 2.1 or SMB 3.x
       57 + * Support) as the minimum so we'll use that.
       58 + */
       59 +uint32_t smb2_old_rwsize = (1<<16);     /* 64KB */
       60 +
       61 +/*
  53   62   * List of all SMB2 versions we implement.  Note that the
  54   63   * highest version we support may be limited by the
  55   64   * _cfg.skc_max_protocol setting.
  56   65   */
  57   66  static uint16_t smb2_versions[] = {
  58   67          0x202,  /* SMB 2.002 */
  59   68          0x210,  /* SMB 2.1 */
  60   69  };
  61   70  static uint16_t smb2_nversions =
  62   71      sizeof (smb2_versions) / sizeof (smb2_versions[0]);
  63   72  
  64   73  static boolean_t
  65   74  smb2_supported_version(smb_session_t *s, uint16_t version)
  66   75  {
  67   76          int i;
  68   77  
  69   78          if (version > s->s_cfg.skc_max_protocol)
  70   79                  return (B_FALSE);
  71   80          for (i = 0; i < smb2_nversions; i++)
  72   81                  if (version == smb2_versions[i])
  73   82                          return (B_TRUE);
  74   83          return (B_FALSE);
  75   84  }
  76   85  
  77   86  /*
  78   87   * Helper for the (SMB1) smb_com_negotiate().  This is the
  79   88   * very unusual protocol interaction where an SMB1 negotiate
  80   89   * gets an SMB2 negotiate response.  This is the normal way
  81   90   * clients first find out if the server supports SMB2.
  82   91   *
  83   92   * Note: This sends an SMB2 reply _itself_ and then returns
  84   93   * SDRC_NO_REPLY so the caller will not send an SMB1 reply.
  85   94   * Also, this is called directly from the reader thread, so
  86   95   * we know this is the only thread using this session.
  87   96   *
  88   97   * The caller frees this request.
  89   98   */
  90   99  smb_sdrc_t
  91  100  smb1_negotiate_smb2(smb_request_t *sr)
  92  101  {
  93  102          smb_session_t *s = sr->session;
  94  103          smb_arg_negotiate_t *negprot = sr->sr_negprot;
  95  104          uint16_t smb2_version;
  96  105          uint16_t secmode2;
  97  106          int rc;
  98  107  
  99  108          /*
 100  109           * Note: In the SMB1 negotiate command handler, we
 101  110           * agreed with one of the SMB2 dialects.  If that
 102  111           * dialect was "SMB 2.002", we'll respond here with
 103  112           * version 0x202 and negotiation is done.  If that
 104  113           * dialect was "SMB 2.???", we'll respond here with
 105  114           * the "wildcard" version 0x2FF, and the client will
 106  115           * come back with an SMB2 negotiate.
 107  116           */
 108  117          switch (negprot->ni_dialect) {
 109  118          case DIALECT_SMB2002:   /* SMB 2.002 (a.k.a. SMB2.0) */
 110  119                  smb2_version = 0x202;
 111  120                  s->dialect = smb2_version;
 112  121                  s->s_state = SMB_SESSION_STATE_NEGOTIATED;
 113  122                  /* Allow normal SMB2 requests now. */
 114  123                  s->newrq_func = smb2sr_newrq;
 115  124  
 116  125                  /*
 117  126                   * Translate SMB1 sec. mode to SMB2.
 118  127                   */
 119  128                  secmode2 = 0;
 120  129                  if (s->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)
 121  130                          secmode2 |= SMB2_NEGOTIATE_SIGNING_ENABLED;
 122  131                  if (s->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
 123  132                          secmode2 |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
 124  133                  s->secmode = secmode2;
 125  134                  break;
 126  135          case DIALECT_SMB2XXX:   /* SMB 2.??? (wildcard vers) */
 127  136                  /*
 128  137                   * Expecting an SMB2 negotiate next, so keep the
 129  138                   * initial s->newrq_func.  Note that secmode is
 130  139                   * fiction good enough to pass the signing check
 131  140                   * in smb2_negotiate_common().  We'll check the
 132  141                   * real secmode when the 2nd negotiate comes.
 133  142                   */
 134  143                  smb2_version = 0x2FF;
 135  144                  s->secmode = SMB2_NEGOTIATE_SIGNING_ENABLED;
 136  145                  break;
 137  146          default:
 138  147                  return (SDRC_DROP_VC);
 139  148          }
 140  149  
 141  150          /*
 142  151           * We did not decode an SMB2 header, so make sure
 143  152           * the SMB2 header fields are initialized.
 144  153           * (Most are zero from smb_request_alloc.)
 145  154           * Also, the SMB1 common dispatch code reserved space
 146  155           * for an SMB1 header, which we need to undo here.
 147  156           */
 148  157          sr->smb2_reply_hdr = sr->reply.chain_offset = 0;
 149  158          sr->smb2_cmd_code = SMB2_NEGOTIATE;
 150  159  
 151  160          rc = smb2_negotiate_common(sr, smb2_version);
 152  161          if (rc != 0)
 153  162                  return (SDRC_DROP_VC);
 154  163  
 155  164          return (SDRC_NO_REPLY);
 156  165  }
 157  166  
 158  167  /*
 159  168   * SMB2 Negotiate gets special handling.  This is called directly by
 160  169   * the reader thread (see smbsr_newrq_initial) with what _should_ be
 161  170   * an SMB2 Negotiate.  Only the "\feSMB" header has been checked
 162  171   * when this is called, so this needs to check the SMB command,
 163  172   * if it's Negotiate execute it, then send the reply, etc.
 164  173   *
 165  174   * Since this is called directly from the reader thread, we
 166  175   * know this is the only thread currently using this session.
 167  176   * This has to duplicate some of what smb2sr_work does as a
 168  177   * result of bypassing the normal dispatch mechanism.
 169  178   *
 170  179   * The caller always frees this request.
 171  180   */
 172  181  int
 173  182  smb2_newrq_negotiate(smb_request_t *sr)
 174  183  {
 175  184          smb_session_t *s = sr->session;
 176  185          int i, rc;
 177  186          uint16_t struct_size;
 178  187          uint16_t best_version;
 179  188          uint16_t version_cnt;
 180  189          uint16_t cl_versions[8];
 181  190  
 182  191          sr->smb2_cmd_hdr = sr->command.chain_offset;
 183  192          rc = smb2_decode_header(sr);
 184  193          if (rc != 0)
 185  194                  return (rc);
 186  195  
 187  196          if ((sr->smb2_cmd_code != SMB2_NEGOTIATE) ||
 188  197              (sr->smb2_next_command != 0))
 189  198                  return (SDRC_DROP_VC);
 190  199  
 191  200          /*
 192  201           * Decode SMB2 Negotiate (fixed-size part)
 193  202           */
 194  203          rc = smb_mbc_decodef(
 195  204              &sr->command, "www..l16.8.",
 196  205              &struct_size,       /* w */
 197  206              &version_cnt,       /* w */
 198  207              &s->secmode,        /* w */
 199  208              /* reserved         (..) */
 200  209              &s->capabilities);  /* l */
 201  210              /* clnt_uuid         16. */
 202  211              /* start_time         8. */
 203  212          if (rc != 0)
 204  213                  return (rc);
 205  214          if (struct_size != 36 || version_cnt > 8)
 206  215                  return (SDRC_DROP_VC);
 207  216  
 208  217          /*
 209  218           * Decode SMB2 Negotiate (variable part)
 210  219           */
 211  220          rc = smb_mbc_decodef(&sr->command,
 212  221              "#w", version_cnt, cl_versions);
 213  222          if (rc != 0)
 214  223                  return (SDRC_DROP_VC);
 215  224  
 216  225          /*
 217  226           * The client offers an array of protocol versions it
 218  227           * supports, which we have decoded into cl_versions[].
 219  228           * We walk the array and pick the highest supported.
 220  229           */
 221  230          best_version = 0;
 222  231          for (i = 0; i < version_cnt; i++)
 223  232                  if (smb2_supported_version(s, cl_versions[i]) &&
 224  233                      best_version < cl_versions[i])
 225  234                          best_version = cl_versions[i];
 226  235          if (best_version == 0)
 227  236                  return (SDRC_DROP_VC);
 228  237          s->dialect = best_version;
 229  238  
 230  239          /* Allow normal SMB2 requests now. */
 231  240          s->s_state = SMB_SESSION_STATE_NEGOTIATED;
 232  241          s->newrq_func = smb2sr_newrq;
 233  242  
 234  243          rc = smb2_negotiate_common(sr, best_version);
 235  244          if (rc != 0)
 236  245                  return (SDRC_DROP_VC);
 237  246  
 238  247          return (0);
 239  248  }
 240  249  
 241  250  /*
  
    | 
      ↓ open down ↓ | 
    179 lines elided | 
    
      ↑ open up ↑ | 
  
 242  251   * Common parts of SMB2 Negotiate, used for both the
 243  252   * SMB1-to-SMB2 style, and straight SMB2 style.
 244  253   * Do negotiation decisions, encode, send the reply.
 245  254   */
 246  255  static int
 247  256  smb2_negotiate_common(smb_request_t *sr, uint16_t version)
 248  257  {
 249  258          timestruc_t boot_tv, now_tv;
 250  259          smb_session_t *s = sr->session;
 251  260          int rc;
      261 +        uint32_t max_rwsize;
 252  262          uint16_t secmode;
 253  263  
 254  264          sr->smb2_status = 0;
 255  265  
 256  266          /*
 257  267           * Negotiation itself.  First the Security Mode.
 258  268           * The caller stashed the client's secmode in s->secmode,
 259  269           * which we validate, and then replace with the server's
 260  270           * secmode, which is all we care about after this.
 261  271           */
 262  272          secmode = SMB2_NEGOTIATE_SIGNING_ENABLED;
 263  273          if (sr->sr_cfg->skc_signing_required) {
 264  274                  secmode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
 265  275                  /* Make sure client at least enables signing. */
 266  276                  if ((s->secmode & secmode) == 0) {
 267  277                          sr->smb2_status = NT_STATUS_INVALID_PARAMETER;
 268  278                  }
 269  279          }
 270  280          s->secmode = secmode;
 271  281  
 272  282          s->cmd_max_bytes = smb2_tcp_bufsize;
 273  283          s->reply_max_bytes = smb2_tcp_bufsize;
 274  284  
 275  285          /*
 276  286           * "The number of credits held by the client MUST be considered
 277  287           * as 1 when the connection is established." [MS-SMB2]
 278  288           * We leave credits at 1 until the first successful
 279  289           * session setup is completed.
 280  290           */
 281  291          s->s_cur_credits = s->s_max_credits = 1;
 282  292          sr->smb2_credit_response = 1;
 283  293  
 284  294          boot_tv.tv_sec = smb_get_boottime();
 285  295          boot_tv.tv_nsec = 0;
 286  296          now_tv.tv_sec = gethrestime_sec();
 287  297          now_tv.tv_nsec = 0;
 288  298  
 289  299          /*
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
 290  300           * SMB2 negotiate reply
 291  301           */
 292  302          sr->smb2_hdr_flags = SMB2_FLAGS_SERVER_TO_REDIR;
 293  303          (void) smb2_encode_header(sr, B_FALSE);
 294  304          if (sr->smb2_status != 0) {
 295  305                  smb2sr_put_error(sr, sr->smb2_status);
 296  306                  smb2_send_reply(sr);
 297  307                  return (-1); /* will drop */
 298  308          }
 299  309  
      310 +        /*
      311 +         * See notes above smb2_max_rwsize, smb2_old_rwsize
      312 +         */
      313 +        if (s->capabilities & SMB2_CAP_LARGE_MTU)
      314 +                max_rwsize = smb2_max_rwsize;
      315 +        else
      316 +                max_rwsize = smb2_old_rwsize;
      317 +
 300  318          rc = smb_mbc_encodef(
 301  319              &sr->reply,
 302  320              "wwww#cllllTTwwl#c",
 303  321              65, /* StructSize */        /* w */
 304  322              s->secmode,                 /* w */
 305  323              version,                    /* w */
 306  324              0, /* reserved */           /* w */
 307  325              UUID_LEN,                   /* # */
 308  326              &s->s_cfg.skc_machine_uuid, /* c */
 309  327              smb2srv_capabilities,       /* l */
 310  328              smb2_max_trans,             /* l */
 311      -            smb2_max_rwsize,            /* l */
 312      -            smb2_max_rwsize,            /* l */
      329 +            max_rwsize,                 /* l */
      330 +            max_rwsize,                 /* l */
 313  331              &now_tv,                    /* T */
 314  332              &boot_tv,                   /* T */
 315  333              128, /* SecBufOff */        /* w */
 316  334              sr->sr_cfg->skc_negtok_len, /* w */
 317  335              0,  /* reserved */          /* l */
 318  336              sr->sr_cfg->skc_negtok_len, /* # */
 319  337              sr->sr_cfg->skc_negtok);    /* c */
 320  338  
 321  339          smb2_send_reply(sr);
 322  340  
 323  341          (void) ksocket_setsockopt(s->sock, SOL_SOCKET,
 324  342              SO_SNDBUF, (const void *)&smb2_tcp_bufsize,
 325  343              sizeof (smb2_tcp_bufsize), CRED());
 326  344          (void) ksocket_setsockopt(s->sock, SOL_SOCKET,
 327  345              SO_RCVBUF, (const void *)&smb2_tcp_bufsize,
 328  346              sizeof (smb2_tcp_bufsize), CRED());
 329  347  
 330  348          return (rc);
 331  349  }
 332  350  
 333  351  /*
 334  352   * SMB2 Dispatch table handler, which will run if we see an
 335  353   * SMB2_NEGOTIATE after the initial negotiation is done.
 336  354   * That would be a protocol error.
 337  355   */
 338  356  smb_sdrc_t
 339  357  smb2_negotiate(smb_request_t *sr)
 340  358  {
 341  359          sr->smb2_status = NT_STATUS_INVALID_PARAMETER;
 342  360          return (SDRC_ERROR);
 343  361  }
 344  362  
 345  363  /*
 346  364   * VALIDATE_NEGOTIATE_INFO [MS-SMB2] 2.2.32.6
 347  365   */
 348  366  uint32_t
 349  367  smb2_fsctl_vneginfo(smb_request_t *sr, smb_fsctl_t *fsctl)
 350  368  {
 351  369          smb_session_t *s = sr->session;
 352  370          int rc;
 353  371  
 354  372          /*
 355  373           * The spec. says to parse the VALIDATE_NEGOTIATE_INFO here
 356  374           * and verify that the original negotiate was not modified.
 357  375           * The only tampering we need worry about is secmode, and
 358  376           * we're not taking that from the client, so don't bother.
 359  377           *
 360  378           * One interesting requirement here is that we MUST reply
 361  379           * with exactly the same information as we returned in our
 362  380           * original reply to the SMB2 negotiate on this session.
 363  381           * If we don't the client closes the connection.
 364  382           */
 365  383  
 366  384          rc = smb_mbc_encodef(
 367  385              fsctl->out_mbc, "l#cww",
 368  386              smb2srv_capabilities,       /* l */
 369  387              UUID_LEN,                   /* # */
 370  388              &s->s_cfg.skc_machine_uuid, /* c */
 371  389              s->secmode,                 /* w */
 372  390              s->dialect);                /* w */
 373  391          if (rc)
 374  392                  return (NT_STATUS_INTERNAL_ERROR);
 375  393  
 376  394          return (0);
 377  395  }
  
    | 
      ↓ open down ↓ | 
    55 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX