Print this page
NEX-17589 Get "too high" smbd error when copy big file to cifs share
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-17795 SMB logon should tolerate idmap problems
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9190 Files with owners not in /etc/passwd and not having inherited ACL's are prevented from seeing ownership/permissions via SMB
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_idmap.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_idmap.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * SMB server interface to idmap
  28   28   * (smb_idmap_get..., smb_idmap_batch_...)
  29   29   *
  30      - * There are three implementations of this interface:
  31      - *      uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
  32      - *      lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
  33      - *      lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
       30 + * There are three implementations of this interface.
       31 + * This is the kernel version of these routines.  See also:
       32 + * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
       33 + * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c
  34   34   *
  35   35   * There are enough differences (relative to the code size)
  36   36   * that it's more trouble than it's worth to merge them.
  37   37   *
  38   38   * This one differs from the others in that it:
  39   39   *      calls kernel (kidmap_...) interfaces
  40      - *      domain SIDs are shared, not strdup'ed
       40 + *      returned domain SIDs are shared, not strdup'ed
  41   41   */
  42   42  
  43   43  /*
  44   44   * SMB ID mapping
  45   45   *
  46   46   * Solaris ID mapping service (aka Winchester) works with domain SIDs
  47   47   * and RIDs where domain SIDs are in string format. CIFS service works
  48   48   * with binary SIDs understandable by CIFS clients. A layer of SMB ID
  49   49   * mapping functions are implemeted to hide the SID conversion details
  50   50   * and also hide the handling of array of batch mapping requests.
↓ open down ↓ 46 lines elided ↑ open up ↑
  97   97                  sim.sim_domsid = "S-1-1";
  98   98                  sim.sim_rid = 0;
  99   99                  sim.sim_stat = IDMAP_SUCCESS;
 100  100                  break;
 101  101  
 102  102          default:
 103  103                  ASSERT(0);
 104  104                  return (IDMAP_ERR_ARG);
 105  105          }
 106  106  
      107 +        /*
      108 +         * IDMAP_ERR_NOTFOUND is an advisory error
      109 +         * and idmap will generate a local sid.
      110 +         */
      111 +        if (sim.sim_stat == IDMAP_ERR_NOTFOUND &&
      112 +            sim.sim_domsid != NULL)
      113 +                sim.sim_stat = IDMAP_SUCCESS;
      114 +
 107  115          if (sim.sim_stat != IDMAP_SUCCESS)
 108  116                  return (sim.sim_stat);
 109  117  
 110  118          if (sim.sim_domsid == NULL)
 111  119                  return (IDMAP_ERR_NOMAPPING);
 112  120  
 113  121          sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
 114  122          if (sim.sim_sid == NULL)
 115  123                  return (IDMAP_ERR_INTERNAL);
 116  124  
↓ open down ↓ 50 lines elided ↑ open up ↑
 167  175  }
 168  176  
 169  177  /*
 170  178   * smb_idmap_batch_create
 171  179   *
 172  180   * Creates and initializes the context for batch ID mapping.
 173  181   */
 174  182  idmap_stat
 175  183  smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
 176  184  {
 177      -        ASSERT(sib);
      185 +        ASSERT(sib != NULL);
 178  186  
 179  187          bzero(sib, sizeof (smb_idmap_batch_t));
 180  188  
 181  189          sib->sib_idmaph = kidmap_get_create(global_zone);
 182  190  
 183  191          sib->sib_flags = flags;
 184  192          sib->sib_nmap = nmap;
 185  193          sib->sib_size = nmap * sizeof (smb_idmap_t);
 186  194          sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
 187  195  
↓ open down ↓ 6 lines elided ↑ open up ↑
 194  202   * Frees the batch ID mapping context.
 195  203   * If ID mapping is Solaris -> Windows it frees memories
 196  204   * allocated for binary SIDs.
 197  205   */
 198  206  void
 199  207  smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
 200  208  {
 201  209          char *domsid;
 202  210          int i;
 203  211  
 204      -        ASSERT(sib);
 205      -        ASSERT(sib->sib_maps);
      212 +        ASSERT(sib != NULL);
      213 +        ASSERT(sib->sib_maps != NULL);
 206  214  
 207      -        if (sib->sib_idmaph)
      215 +        if (sib->sib_idmaph) {
 208  216                  kidmap_get_destroy(sib->sib_idmaph);
      217 +                sib->sib_idmaph = NULL;
      218 +        }
 209  219  
 210  220          if (sib->sib_flags & SMB_IDMAP_ID2SID) {
 211  221                  /*
 212  222                   * SIDs are allocated only when mapping
 213  223                   * UID/GID to SIDs
 214  224                   */
 215  225                  for (i = 0; i < sib->sib_nmap; i++)
 216  226                          smb_sid_free(sib->sib_maps[i].sim_sid);
 217  227          } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
 218  228                  /*
 219  229                   * SID prefixes are allocated only when mapping
 220  230                   * SIDs to UID/GID
 221  231                   */
 222  232                  for (i = 0; i < sib->sib_nmap; i++) {
 223  233                          domsid = sib->sib_maps[i].sim_domsid;
 224  234                          if (domsid)
 225  235                                  smb_mem_free(domsid);
 226  236                  }
 227  237          }
 228  238  
 229      -        if (sib->sib_size && sib->sib_maps)
      239 +        if (sib->sib_size && sib->sib_maps) {
 230  240                  kmem_free(sib->sib_maps, sib->sib_size);
      241 +                sib->sib_maps = NULL;
      242 +        }
 231  243  }
 232  244  
 233  245  /*
 234  246   * smb_idmap_batch_getid
 235  247   *
 236  248   * Queue a request to map the given SID to a UID or GID.
 237  249   *
 238  250   * sim->sim_id should point to variable that's supposed to
 239  251   * hold the returned UID/GID. This needs to be setup by caller
 240  252   * of this function.
↓ open down ↓ 1 lines elided ↑ open up ↑
 242  254   * If requested ID type is known, it's passed as 'idtype',
 243  255   * if it's unknown it'll be returned in sim->sim_idtype.
 244  256   */
 245  257  idmap_stat
 246  258  smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 247  259      smb_sid_t *sid, int idtype)
 248  260  {
 249  261          char strsid[SMB_SID_STRSZ];
 250  262          idmap_stat idm_stat;
 251  263  
 252      -        ASSERT(idmaph);
 253      -        ASSERT(sim);
 254      -        ASSERT(sid);
      264 +        ASSERT(idmaph != NULL);
      265 +        ASSERT(sim != NULL);
      266 +        ASSERT(sid != NULL);
 255  267  
 256  268          smb_sid_tostr(sid, strsid);
 257  269          if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
 258  270                  return (IDMAP_ERR_SID);
      271 +        /* Note: Free sim_domsid in smb_idmap_batch_destroy */
 259  272          sim->sim_domsid = smb_mem_strdup(strsid);
      273 +        sim->sim_idtype = idtype;
 260  274  
 261  275          switch (idtype) {
 262  276          case SMB_IDMAP_USER:
 263  277                  idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
 264  278                      sim->sim_rid, sim->sim_id, &sim->sim_stat);
 265  279                  break;
 266  280  
 267  281          case SMB_IDMAP_GROUP:
 268  282                  idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
 269  283                      sim->sim_rid, sim->sim_id, &sim->sim_stat);
↓ open down ↓ 13 lines elided ↑ open up ↑
 283  297          return (idm_stat);
 284  298  }
 285  299  
 286  300  /*
 287  301   * smb_idmap_batch_getsid
 288  302   *
 289  303   * Queue a request to map the given UID/GID to a SID.
 290  304   *
 291  305   * sim->sim_domsid and sim->sim_rid will contain the mapping
 292  306   * result upon successful process of the batched request.
      307 + * Stash the type for error reporting (caller saves the ID).
 293  308   */
 294  309  idmap_stat
 295  310  smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
 296  311      uid_t id, int idtype)
 297  312  {
 298  313          idmap_stat idm_stat;
 299  314  
      315 +        sim->sim_idtype = idtype;
 300  316          switch (idtype) {
 301  317          case SMB_IDMAP_USER:
 302  318                  idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
 303  319                      (const char **)&sim->sim_domsid, &sim->sim_rid,
 304  320                      &sim->sim_stat);
 305  321                  break;
 306  322  
 307  323          case SMB_IDMAP_GROUP:
 308  324                  idm_stat = kidmap_batch_getsidbygid(idmaph, id,
 309  325                      (const char **)&sim->sim_domsid, &sim->sim_rid,
↓ open down ↓ 25 lines elided ↑ open up ↑
 335  351                  break;
 336  352  
 337  353          default:
 338  354                  ASSERT(0);
 339  355                  return (IDMAP_ERR_ARG);
 340  356          }
 341  357  
 342  358          return (idm_stat);
 343  359  }
 344  360  
      361 +static void
      362 +smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim)
      363 +{
      364 +
      365 +        if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
      366 +                /*
      367 +                 * Note: The ID and type we asked idmap to map
      368 +                 * were saved in *sim_id and sim_idtype.
      369 +                 */
      370 +                uint_t id = (sim->sim_id == NULL) ?
      371 +                    0 : (uint_t)*sim->sim_id;
      372 +                cmn_err(CE_WARN, "Can't get SID for "
      373 +                    "ID=%u type=%d, status=%d",
      374 +                    id, sim->sim_idtype, sim->sim_stat);
      375 +        }
      376 +
      377 +        if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
      378 +                cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d",
      379 +                    sim->sim_domsid, sim->sim_rid, sim->sim_stat);
      380 +        }
      381 +}
      382 +
 345  383  /*
 346  384   * smb_idmap_batch_getmappings
 347  385   *
 348  386   * trigger ID mapping service to get the mappings for queued
 349  387   * requests.
 350  388   *
 351  389   * Checks the result of all the queued requests.
 352  390   * If this is a Solaris -> Windows mapping it generates
 353  391   * binary SIDs from returned (domsid, rid) pairs.
 354  392   */
 355  393  idmap_stat
 356  394  smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
 357  395  {
 358  396          idmap_stat idm_stat = IDMAP_SUCCESS;
      397 +        smb_idmap_t *sim;
 359  398          int i;
 360  399  
 361  400          idm_stat = kidmap_get_mappings(sib->sib_idmaph);
 362  401          if (idm_stat != IDMAP_SUCCESS)
 363  402                  return (idm_stat);
 364  403  
 365  404          /*
 366  405           * Check the status for all the queued requests
 367  406           */
 368      -        for (i = 0; i < sib->sib_nmap; i++) {
 369      -                if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
 370      -                        return (sib->sib_maps[i].sim_stat);
      407 +        for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
      408 +                if (sim->sim_stat != IDMAP_SUCCESS) {
      409 +                        smb_idmap_bgm_report(sib, sim);
      410 +                        if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) {
      411 +                                return (sim->sim_stat);
      412 +                        }
      413 +                }
 371  414          }
 372  415  
 373  416          if (smb_idmap_batch_binsid(sib) != 0)
 374  417                  idm_stat = IDMAP_ERR_OTHER;
 375  418  
 376  419          return (idm_stat);
 377  420  }
 378  421  
 379  422  /*
 380  423   * smb_idmap_batch_binsid
↓ open down ↓ 8 lines elided ↑ open up ↑
 389  432          smb_sid_t *sid;
 390  433          smb_idmap_t *sim;
 391  434          int i;
 392  435  
 393  436          if (sib->sib_flags & SMB_IDMAP_SID2ID)
 394  437                  /* This operation is not required */
 395  438                  return (0);
 396  439  
 397  440          sim = sib->sib_maps;
 398  441          for (i = 0; i < sib->sib_nmap; sim++, i++) {
 399      -                ASSERT(sim->sim_domsid);
      442 +                ASSERT(sim->sim_domsid != NULL);
 400  443                  if (sim->sim_domsid == NULL)
 401  444                          return (1);
 402  445  
 403  446                  if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
 404  447                          return (1);
 405  448  
 406  449                  sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
 407  450                  smb_sid_free(sid);
 408  451          }
 409  452  
 410  453          return (0);
 411  454  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX