Print this page
    
NEX-18462 SMB can't view ACL if posix ID can't be mapped
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/idmap/idmap_kapi.c
          +++ new/usr/src/uts/common/idmap/idmap_kapi.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  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.
  
    | 
      ↓ 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  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
       25 + *
       26 + * Copyright 2018 Nexenta Systems, Inc.
  25   27   */
  26   28  
  27   29  /*
  28   30   * Windows to Solaris Identity Mapping kernel API
  29   31   * This module provides an API to map Windows SIDs to
  30   32   * Solaris UID and GIDs.
  31   33   */
  32   34  
  33   35  
  34   36  #include <sys/types.h>
  35   37  #include <sys/ksynch.h>
  36   38  #include <sys/door.h>
  37   39  #include <rpc/rpc_msg.h>
  38   40  #include <rpc/xdr.h>
  39   41  #include <rpc/auth.h>
  40   42  #include <rpc/rpc_sztypes.h>
  41   43  #ifdef  DEBUG
  42   44  #include <sys/cmn_err.h>
  43   45  #endif  /* DEBUG */
  44   46  #include <sys/proc.h>
  45   47  #include <sys/sunddi.h>
  46   48  #include <sys/param.h>
  47   49  #include <sys/atomic.h>
  48   50  #include <sys/sysmacros.h>
  49   51  #include <sys/disp.h>
  50   52  #include <sys/kidmap.h>
  51   53  #include <sys/zone.h>
  52   54  #include <rpcsvc/idmap_prot.h>
  53   55  #include "kidmap_priv.h"
  54   56  
  55   57  
  56   58  /*
  57   59   * Defined types
  58   60   */
  59   61  
  60   62  
  61   63  /*
  62   64   * This structure holds pointers for the
  63   65   * batch mapping results.
  64   66   */
  65   67  typedef struct idmap_get_res {
  66   68          idmap_id_type   idtype;
  67   69          uid_t           *uid;
  68   70          gid_t           *gid;
  69   71          uid_t           *pid;
  70   72          int             *is_user;
  71   73          const char      **sid_prefix;
  72   74          uint32_t        *rid;
  73   75          idmap_stat      *stat;
  74   76  } idmap_get_res;
  75   77  
  76   78  /* Batch mapping handle structure */
  77   79  struct idmap_get_handle {
  78   80          struct idmap_zone_specific *zs;
  79   81          int             mapping_num;
  80   82          int             mapping_size;
  81   83          idmap_mapping   *mapping;
  82   84          idmap_get_res   *result;
  83   85  };
  84   86  
  85   87  
  86   88  /* Zone specific data */
  87   89  typedef struct idmap_zone_specific {
  88   90          zoneid_t        zone_id;
  89   91          kmutex_t        zone_mutex;
  90   92          idmap_cache_t   cache;
  91   93          door_handle_t   door_handle;
  92   94          int             door_valid;
  93   95          int             door_retried;
  94   96          uint32_t        message_id;
  95   97  } idmap_zone_specific_t;
  96   98  
  97   99  
  98  100  
  99  101  /*
 100  102   * Module global data
 101  103   */
 102  104  
 103  105  static kmutex_t         idmap_zone_mutex;
 104  106  static zone_key_t       idmap_zone_key;
 105  107  
 106  108  
 107  109  /*
 108  110   * Local function definitions
 109  111   */
 110  112  
 111  113  
 112  114  static int
 113  115  kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op,
 114  116      xdrproc_t xdr_args, caddr_t args, xdrproc_t xdr_res, caddr_t res);
 115  117  
 116  118  static int
 117  119  kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg);
 118  120  
 119  121  static idmap_zone_specific_t *
 120  122  idmap_get_zone_specific(zone_t *zone);
 121  123  
 122  124  
 123  125  
 124  126  int
 125  127  idmap_reg_dh(zone_t *zone, door_handle_t dh)
 126  128  {
 127  129          idmap_zone_specific_t *zs;
 128  130  
 129  131          zs = idmap_get_zone_specific(zone);
 130  132  
 131  133          mutex_enter(&zs->zone_mutex);
 132  134  
 133  135          if (zs->door_valid)
 134  136                  door_ki_rele(zs->door_handle);
 135  137  
 136  138          zs->door_handle = dh;
 137  139          zs->door_valid = 1;
 138  140  
 139  141          mutex_exit(&zs->zone_mutex);
 140  142  
 141  143          return (0);
 142  144  }
 143  145  
 144  146  /*
 145  147   * idmap_unreg_dh
 146  148   *
 147  149   * This routine is called by system call idmap_unreg().
 148  150   * idmap_unreg() calls door_ki_rele() on the supplied
 149  151   * door handle after this routine returns. We only
 150  152   * need to perform one door release on zs->door_handle
 151  153   */
 152  154  int
 153  155  idmap_unreg_dh(zone_t *zone, door_handle_t dh)
 154  156  {
 155  157          idmap_zone_specific_t *zs;
 156  158  
 157  159          zs = idmap_get_zone_specific(zone);
 158  160  
 159  161          kidmap_cache_purge(&zs->cache);
 160  162  
 161  163          mutex_enter(&zs->zone_mutex);
 162  164  
 163  165          if (!zs->door_valid || zs->door_handle != dh) {
 164  166                  mutex_exit(&zs->zone_mutex);
 165  167                  return (EINVAL);
 166  168          }
 167  169  
 168  170          door_ki_rele(zs->door_handle);
 169  171  
 170  172          zs->door_valid = 0;
 171  173          zs->door_retried = 0;
 172  174          mutex_exit(&zs->zone_mutex);
 173  175  
 174  176          return (0);
 175  177  }
 176  178  
 177  179  
 178  180  /*
 179  181   * IMPORTANT. This function idmap_get_cache_data() is project
 180  182   * private and is for use of the test system only and should
 181  183   * not be used for other purposes.
 182  184   */
 183  185  void
 184  186  idmap_get_cache_data(zone_t *zone, size_t *uidbysid, size_t *gidbysid,
 185  187      size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid)
 186  188  {
 187  189          idmap_zone_specific_t *zs;
 188  190  
 189  191          zs = idmap_get_zone_specific(zone);
 190  192  
 191  193          kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid,
 192  194              pidbysid, sidbyuid, sidbygid);
 193  195  }
 194  196  
 195  197  static int
 196  198  kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg)
 197  199  {
 198  200          door_handle_t   dh;
 199  201          door_info_t     di;
 200  202          int             status = 0;
 201  203          int             num_retries = 5;
 202  204          int             door_retried = 0;
 203  205  
 204  206  retry:
 205  207          mutex_enter(&zs->zone_mutex);
 206  208          if (zs->door_valid) {
 207  209                  dh = zs->door_handle;
 208  210                  door_ki_hold(dh);
 209  211          } else {
 210  212                  dh = NULL;
 211  213                  door_retried = zs->door_retried;
 212  214          }
 213  215          mutex_exit(&zs->zone_mutex);
 214  216  
 215  217          if (dh == NULL) {
 216  218                  /* The door has been retried before so dont wait */
 217  219                  if (door_retried)
 218  220                          return (-1);
 219  221  
 220  222                  /*
 221  223                   * There is no door handle yet. Give
 222  224                   * smf a chance to restart idmapd
 223  225                   */
 224  226                  if (num_retries-- > 0) {
 225  227                          delay(hz);
 226  228                          goto retry;
 227  229                  }
 228  230  
 229  231  #ifdef  DEBUG
 230  232                  zcmn_err(zs->zone_id, CE_WARN,
 231  233                      "idmap: Error no registered door to call the "
 232  234                      "idmap daemon\n");
 233  235  #endif
 234  236                  mutex_enter(&zs->zone_mutex);
 235  237                  if (!zs->door_valid)
 236  238                          zs->door_retried = 1;
 237  239                  mutex_exit(&zs->zone_mutex);
 238  240  
 239  241                  return (-1);
 240  242          }
 241  243  
 242  244          status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0);
 243  245  
 244  246          switch (status) {
 245  247          case 0: /* Success */
 246  248                  door_ki_rele(dh);
 247  249                  return (0);
 248  250  
 249  251          case EINTR:
 250  252                  /* If we took an interrupt we have to bail out. */
 251  253                  if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) {
 252  254                          door_ki_rele(dh);
 253  255  #ifdef  DEBUG
 254  256                          zcmn_err(zs->zone_id, CE_WARN,
 255  257                              "idmap: Interrupted\n");
 256  258  #endif
 257  259                          return (-1);
 258  260                  }
 259  261                  /*
 260  262                   * Just retry and see what happens.
 261  263                   */
 262  264                  /* FALLTHROUGH */
 263  265  
 264  266          case EAGAIN:
 265  267                  /* A resouce problem */
 266  268                  door_ki_rele(dh);
 267  269                  /* Back off before retrying */
 268  270  #ifdef  DEBUG
 269  271                  zcmn_err(zs->zone_id, CE_WARN,
 270  272                      "idmap: Door call returned error %d. Retrying\n", status);
 271  273  #endif  /* DEBUG */
 272  274                  delay(hz);
 273  275                  goto retry;
 274  276  
 275  277          case EBADF:
 276  278                  /* Stale door handle. See if smf restarts the daemon. */
 277  279                  door_ki_rele(dh);
 278  280                  mutex_enter(&zs->zone_mutex);
 279  281                  if (zs->door_valid && dh == zs->door_handle) {
 280  282                          zs->door_valid = 0;
 281  283                          zs->door_retried = 0;
 282  284                          door_ki_rele(zs->door_handle);
 283  285                  }
 284  286                  mutex_exit(&zs->zone_mutex);
 285  287                  /* Back off before retrying */
 286  288  #ifdef  DEBUG
 287  289                  zcmn_err(zs->zone_id, CE_WARN,
 288  290                      "idmap: Door call returned error %d. Retrying\n", status);
 289  291  #endif  /* DEBUG */
 290  292                  delay(hz);
 291  293                  goto retry;
 292  294  
 293  295          default:
 294  296                  /* Unknown error */
 295  297  #ifdef  DEBUG
 296  298                  zcmn_err(zs->zone_id, CE_WARN,
 297  299                      "idmap: Door call returned error %d.\n", status);
 298  300  #endif  /* DEBUG */
 299  301                  door_ki_rele(dh);
 300  302                  return (-1);
 301  303          }
 302  304  }
 303  305  
 304  306  
 305  307  static idmap_zone_specific_t *
 306  308  idmap_get_zone_specific(zone_t *zone)
 307  309  {
 308  310          idmap_zone_specific_t *zs;
 309  311  
 310  312          ASSERT(zone != NULL);
 311  313  
 312  314          zs = zone_getspecific(idmap_zone_key, zone);
 313  315          if (zs != NULL)
 314  316                  return (zs);
 315  317  
 316  318          mutex_enter(&idmap_zone_mutex);
 317  319          zs = zone_getspecific(idmap_zone_key, zone);
 318  320          if (zs == NULL) {
 319  321                  zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP);
 320  322                  mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL);
 321  323                  kidmap_cache_create(&zs->cache);
 322  324                  zs->zone_id = zone->zone_id;
 323  325                  (void) zone_setspecific(idmap_zone_key, zone, zs);
 324  326                  mutex_exit(&idmap_zone_mutex);
 325  327                  return (zs);
 326  328          }
 327  329          mutex_exit(&idmap_zone_mutex);
 328  330  
 329  331          return (zs);
 330  332  }
 331  333  
 332  334  
 333  335  static void
 334  336  /* ARGSUSED */
 335  337  idmap_zone_destroy(zoneid_t zone_id, void *arg)
 336  338  {
 337  339          idmap_zone_specific_t *zs = arg;
 338  340          if (zs != NULL) {
 339  341                  kidmap_cache_delete(&zs->cache);
 340  342                  if (zs->door_valid) {
 341  343                          door_ki_rele(zs->door_handle);
 342  344                  }
 343  345                  mutex_destroy(&zs->zone_mutex);
 344  346                  kmem_free(zs, sizeof (idmap_zone_specific_t));
 345  347          }
 346  348  }
 347  349  
 348  350  
 349  351  int
 350  352  kidmap_start(void)
 351  353  {
 352  354          mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
 353  355          zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy);
 354  356          kidmap_sid_prefix_store_init();
 355  357  
 356  358          return (0);
 357  359  }
 358  360  
 359  361  
 360  362  int
 361  363  kidmap_stop(void)
 362  364  {
 363  365          return (EBUSY);
 364  366  }
 365  367  
 366  368  
 367  369  /*
 368  370   * idmap_get_door
 369  371   *
 370  372   * This is called by the system call allocids() to get the door for the
 371  373   * given zone.
 372  374   */
 373  375  door_handle_t
 374  376  idmap_get_door(zone_t *zone)
 375  377  {
 376  378          door_handle_t dh = NULL;
 377  379          idmap_zone_specific_t *zs;
 378  380  
 379  381          zs = idmap_get_zone_specific(zone);
 380  382  
 381  383          mutex_enter(&zs->zone_mutex);
 382  384          if (zs->door_valid) {
 383  385                  dh = zs->door_handle;
 384  386                  door_ki_hold(dh);
 385  387          }
 386  388          mutex_exit(&zs->zone_mutex);
 387  389          return (dh);
 388  390  }
 389  391  
 390  392  
 391  393  /*
 392  394   * idmap_purge_cache
 393  395   *
 394  396   * This is called by the system call allocids() to purge the cache for the
 395  397   * given zone.
 396  398   */
 397  399  void
 398  400  idmap_purge_cache(zone_t *zone)
 399  401  {
 400  402          idmap_zone_specific_t *zs;
 401  403  
 402  404          zs = idmap_get_zone_specific(zone);
 403  405  
 404  406          kidmap_cache_purge(&zs->cache);
 405  407  }
 406  408  
 407  409  
 408  410  
 409  411  
 410  412  /*
 411  413   * Given Domain SID and RID, get UID
 412  414   *
 413  415   * Input:
 414  416   * sid_prefix   - Domain SID in canonical form
 415  417   * rid  - RID
 416  418   *
 417  419   * Output:
 418  420   * uid  - POSIX UID if return == IDMAP_SUCCESS
 419  421   *
 420  422   * Return:
 421  423   * Success return IDMAP_SUCCESS else IDMAP error
 422  424   */
 423  425  idmap_stat
 424  426  kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
 425  427      uid_t *uid)
 426  428  {
 427  429          idmap_zone_specific_t   *zs;
 428  430          idmap_mapping_batch     args;
 429  431          idmap_mapping           mapping;
 430  432          idmap_ids_res           results;
 431  433          uint32_t                op = IDMAP_GET_MAPPED_IDS;
 432  434          const char              *new_sid_prefix;
 433  435          idmap_stat              status;
 434  436  
 435  437          if (sid_prefix == NULL || uid == NULL)
 436  438                  return (IDMAP_ERR_ARG);
 437  439  
 438  440          zs = idmap_get_zone_specific(zone);
 439  441  
 440  442          if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid)
 441  443              == IDMAP_SUCCESS)
 442  444                  return (IDMAP_SUCCESS);
 443  445  
 444  446          bzero(&mapping, sizeof (idmap_mapping));
 445  447          mapping.id1.idtype = IDMAP_SID;
 446  448          mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
 447  449          mapping.id1.idmap_id_u.sid.rid = rid;
 448  450          mapping.id2.idtype = IDMAP_UID;
 449  451  
 450  452          bzero(&results, sizeof (idmap_ids_res));
 451  453  
 452  454          args.idmap_mapping_batch_len = 1;
 453  455          args.idmap_mapping_batch_val = &mapping;
 454  456  
 455  457          if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
 456  458              (caddr_t)&args, xdr_idmap_ids_res,
 457  459              (caddr_t)&results) == 0) {
 458  460                  /* Door call succeded */
 459  461                  if (results.retcode != IDMAP_SUCCESS) {
 460  462                          status = results.retcode;
 461  463                          *uid = UID_NOBODY;
 462  464                  } else if (results.ids.ids_len >= 1 &&
 463  465                      results.ids.ids_val[0].id.idtype == IDMAP_UID) {
 464  466                          status = results.ids.ids_val[0].retcode;
 465  467                          *uid = results.ids.ids_val[0].id.idmap_id_u.uid;
 466  468                          if (status == IDMAP_SUCCESS) {
 467  469                                  new_sid_prefix = kidmap_find_sid_prefix(
 468  470                                      sid_prefix);
 469  471                                  kidmap_cache_add_sid2uid(&zs->cache,
 470  472                                      new_sid_prefix, rid, *uid,
 471  473                                      results.ids.ids_val[0].direction);
 472  474                          }
 473  475                  } else {
 474  476                          status = IDMAP_ERR_NOMAPPING;
 475  477                          *uid = UID_NOBODY;
 476  478                  }
 477  479                  xdr_free(xdr_idmap_ids_res, (char *)&results);
 478  480          } else {
 479  481                  /* Door call failed */
 480  482                  status = IDMAP_ERR_NOMAPPING;
 481  483                  *uid = UID_NOBODY;
 482  484          }
 483  485          return (status);
 484  486  }
 485  487  
 486  488  
 487  489  /*
 488  490   * Given Domain SID and RID, get GID
 489  491   *
 490  492   * Input:
 491  493   * sid_prefix   - Domain SID in canonical form
 492  494   * rid  - RID
 493  495   *
 494  496   * Output:
 495  497   * gid  - POSIX UID if return == IDMAP_SUCCESS
 496  498   *
 497  499   * Return:
 498  500   * Success return IDMAP_SUCCESS else IDMAP error
 499  501   */
 500  502  idmap_stat
 501  503  kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
 502  504      gid_t *gid)
 503  505  {
 504  506          idmap_zone_specific_t   *zs;
 505  507          idmap_mapping_batch     args;
 506  508          idmap_mapping           mapping;
 507  509          idmap_ids_res           results;
 508  510          uint32_t                op = IDMAP_GET_MAPPED_IDS;
 509  511          const char              *new_sid_prefix;
 510  512          idmap_stat              status;
 511  513  
 512  514          if (sid_prefix == NULL || gid == NULL)
 513  515                  return (IDMAP_ERR_ARG);
 514  516  
 515  517          zs = idmap_get_zone_specific(zone);
 516  518  
 517  519          if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid)
 518  520              == IDMAP_SUCCESS)
 519  521                  return (IDMAP_SUCCESS);
 520  522  
 521  523          bzero(&mapping, sizeof (idmap_mapping));
 522  524          mapping.id1.idtype = IDMAP_SID;
 523  525          mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
 524  526          mapping.id1.idmap_id_u.sid.rid = rid;
 525  527          mapping.id2.idtype = IDMAP_GID;
 526  528  
 527  529          bzero(&results, sizeof (idmap_ids_res));
 528  530  
 529  531          args.idmap_mapping_batch_len = 1;
 530  532          args.idmap_mapping_batch_val = &mapping;
 531  533  
 532  534          if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
 533  535              (caddr_t)&args, xdr_idmap_ids_res,
 534  536              (caddr_t)&results) == 0) {
 535  537                  /* Door call succeded */
 536  538                  if (results.retcode != IDMAP_SUCCESS) {
 537  539                          status = results.retcode;
 538  540                          *gid = GID_NOBODY;
 539  541                  } else if (results.ids.ids_len >= 1 &&
 540  542                      results.ids.ids_val[0].id.idtype == IDMAP_GID) {
 541  543                          status = results.ids.ids_val[0].retcode;
 542  544                          *gid = results.ids.ids_val[0].id.idmap_id_u.gid;
 543  545                          if (status == IDMAP_SUCCESS) {
 544  546                                  new_sid_prefix = kidmap_find_sid_prefix(
 545  547                                      sid_prefix);
 546  548                                  kidmap_cache_add_sid2gid(&zs->cache,
 547  549                                      new_sid_prefix, rid, *gid,
 548  550                                      results.ids.ids_val[0].direction);
 549  551                          }
 550  552                  } else {
 551  553                          status = IDMAP_ERR_NOMAPPING;
 552  554                          *gid = GID_NOBODY;
 553  555                  }
 554  556                  xdr_free(xdr_idmap_ids_res, (char *)&results);
 555  557          } else {
 556  558                  /* Door call failed */
 557  559                  status = IDMAP_ERR_NOMAPPING;
 558  560                  *gid = GID_NOBODY;
 559  561          }
 560  562          return (status);
 561  563  }
 562  564  
 563  565  /*
 564  566   * Given Domain SID and RID, get Posix ID
 565  567   *
 566  568   * Input:
 567  569   * sid_prefix   - Domain SID in canonical form
 568  570   * rid  - RID
 569  571   *
 570  572   * Output:
 571  573   * pid  - POSIX ID if return == IDMAP_SUCCESS
 572  574   * is_user - 1 == UID, 0 == GID  if return == IDMAP_SUCCESS
 573  575   *
 574  576   * Return:
 575  577   * Success return IDMAP_SUCCESS else IDMAP error
 576  578   */
 577  579  idmap_stat
 578  580  kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
 579  581      uid_t *pid, int *is_user)
 580  582  {
 581  583          idmap_zone_specific_t   *zs;
 582  584          idmap_mapping_batch     args;
 583  585          idmap_mapping           mapping;
 584  586          idmap_ids_res           results;
 585  587          uint32_t                op = IDMAP_GET_MAPPED_IDS;
 586  588          const char              *new_sid_prefix;
 587  589          idmap_stat              status;
 588  590  
 589  591          if (sid_prefix == NULL || pid == NULL || is_user == NULL)
 590  592                  return (IDMAP_ERR_ARG);
 591  593  
 592  594          zs = idmap_get_zone_specific(zone);
 593  595  
 594  596          if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid,
 595  597              is_user) == IDMAP_SUCCESS)
 596  598                  return (IDMAP_SUCCESS);
 597  599  
 598  600          bzero(&mapping, sizeof (idmap_mapping));
 599  601          mapping.id1.idtype = IDMAP_SID;
 600  602          mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
 601  603          mapping.id1.idmap_id_u.sid.rid = rid;
 602  604          mapping.id2.idtype = IDMAP_POSIXID;
 603  605  
 604  606          bzero(&results, sizeof (idmap_ids_res));
 605  607  
 606  608          args.idmap_mapping_batch_len = 1;
 607  609          args.idmap_mapping_batch_val = &mapping;
 608  610  
 609  611          if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
 610  612              (caddr_t)&args, xdr_idmap_ids_res,
 611  613              (caddr_t)&results) == 0) {
 612  614                  /* Door call succeded */
 613  615                  if (results.retcode != IDMAP_SUCCESS) {
 614  616                          status = results.retcode;
 615  617                          *is_user = 1;
 616  618                          *pid = UID_NOBODY;
 617  619                  } else if (results.ids.ids_len >= 1 && (
 618  620                      results.ids.ids_val[0].id.idtype == IDMAP_UID ||
 619  621                      results.ids.ids_val[0].id.idtype == IDMAP_GID)) {
 620  622                          status = results.ids.ids_val[0].retcode;
 621  623                          if (results.ids.ids_val[0].id.idtype == IDMAP_UID) {
 622  624                                  *is_user = 1;
 623  625                                  *pid = results.ids.ids_val[0].id.idmap_id_u.uid;
 624  626                          } else {
 625  627                                  *is_user = 0;
 626  628                                  *pid = results.ids.ids_val[0].id.idmap_id_u.gid;
 627  629                          }
 628  630                          if (status == IDMAP_SUCCESS) {
 629  631                                  new_sid_prefix = kidmap_find_sid_prefix(
 630  632                                      sid_prefix);
 631  633                                  kidmap_cache_add_sid2pid(&zs->cache,
 632  634                                      new_sid_prefix, rid, *pid,
 633  635                                      *is_user,
 634  636                                      results.ids.ids_val[0].direction);
 635  637                          }
 636  638                  } else {
 637  639                          status = IDMAP_ERR_NOMAPPING;
 638  640                          *is_user = 1;
 639  641                          *pid = UID_NOBODY;
 640  642                  }
 641  643                  xdr_free(xdr_idmap_ids_res, (char *)&results);
 642  644          } else {
 643  645                  /* Door call failed */
 644  646                  status = IDMAP_ERR_NOMAPPING;
 645  647                  *is_user = 1;
 646  648                  *pid = UID_NOBODY;
 647  649          }
 648  650          return (status);
 649  651  }
 650  652  
 651  653  
 652  654  /*
 653  655   * Given UID, get Domain SID and RID
 654  656   *
 655  657   * Input:
 656  658   * uid - Posix UID
 657  659   *
 658  660   * Output:
 659  661   * sid_prefix   - Domain SID if return == IDMAP_SUCCESS
 660  662   * rid  - RID if return == IDMAP_SUCCESS
 661  663   *
 662  664   * Return:
 663  665   * Success return IDMAP_SUCCESS else IDMAP error
 664  666   */
 665  667  idmap_stat
 666  668  kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
 667  669      uint32_t *rid)
 668  670  {
 669  671          idmap_zone_specific_t   *zs;
 670  672          idmap_mapping_batch     args;
 671  673          idmap_mapping           mapping;
 672  674          idmap_ids_res           results;
 673  675          uint32_t                op = IDMAP_GET_MAPPED_IDS;
 674  676          idmap_stat              status;
 675  677          time_t                  entry_ttl;
 676  678          idmap_id                *id;
 677  679  
 678  680          if (sid_prefix == NULL || rid == NULL)
 679  681                  return (IDMAP_ERR_ARG);
 680  682  
 681  683          zs = idmap_get_zone_specific(zone);
 682  684  
 683  685          if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid)
 684  686              == IDMAP_SUCCESS) {
 685  687                  return (IDMAP_SUCCESS);
 686  688          }
 687  689  
 688  690          bzero(&mapping, sizeof (idmap_mapping));
 689  691          mapping.id1.idtype = IDMAP_UID;
 690  692          mapping.id1.idmap_id_u.uid = uid;
 691  693          mapping.id2.idtype = IDMAP_SID;
 692  694  
 693  695          bzero(&results, sizeof (idmap_ids_res));
 694  696  
 695  697          args.idmap_mapping_batch_len = 1;
 696  698          args.idmap_mapping_batch_val = &mapping;
 697  699  
 698  700          if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
 699  701              (caddr_t)&args, xdr_idmap_ids_res,
 700  702              (caddr_t)&results) == 0) {
 701  703                  /* Door call succeded */
 702  704                  if (results.retcode != IDMAP_SUCCESS) {
 703  705                          status = results.retcode;
 704  706                          *rid = 0;
 705  707                          *sid_prefix = NULL;
 706  708                  } else if (results.ids.ids_len >= 1 &&
 707  709                      (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
 708  710                      results.ids.ids_val[0].id.idtype == IDMAP_USID ||
 709  711                      results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
 710  712                          status = results.ids.ids_val[0].retcode;
 711  713                          id = &results.ids.ids_val[0].id;
 712  714                          *sid_prefix = kidmap_find_sid_prefix(
 713  715                              id->idmap_id_u.sid.prefix);
 714  716                          *rid = id->idmap_id_u.sid.rid;
 715  717                          if (status == IDMAP_SUCCESS) {
 716  718                                  kidmap_cache_add_sid2uid(&zs->cache,
 717  719                                      *sid_prefix, *rid, uid,
 718  720                                      results.ids.ids_val[0].direction);
 719  721                          }
 720  722                  } else {
 721  723                          status = IDMAP_ERR_NOMAPPING;
 722  724                          *rid = 0;
 723  725                          *sid_prefix = NULL;
 724  726                  }
 725  727                  xdr_free(xdr_idmap_ids_res, (char *)&results);
 726  728          } else {
 727  729                  /* Door call failed */
 728  730                  status = IDMAP_ERR_NOMAPPING;
 729  731                  *rid = 0;
 730  732                  *sid_prefix = NULL;
 731  733          }
 732  734          return (status);
 733  735  }
 734  736  
 735  737  
 736  738  /*
 737  739   * Given GID, get Domain SID and RID
 738  740   *
 739  741   * Input:
 740  742   * gid - Posix GID
 741  743   *
 742  744   * Output:
 743  745   * sid_prefix   - Domain SID if return == IDMAP_SUCCESS
 744  746   * rid  - RID if return == IDMAP_SUCCESS
 745  747   *
 746  748   * Return:
 747  749   * Success return IDMAP_SUCCESS else IDMAP error
 748  750   */
 749  751  idmap_stat
 750  752  kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
 751  753      uint32_t *rid)
 752  754  {
 753  755          idmap_zone_specific_t   *zs;
 754  756          idmap_mapping_batch     args;
 755  757          idmap_mapping           mapping;
 756  758          idmap_ids_res           results;
 757  759          uint32_t                op = IDMAP_GET_MAPPED_IDS;
 758  760          idmap_stat              status;
 759  761          idmap_id                *id;
 760  762  
 761  763          if (sid_prefix == NULL || rid == NULL)
 762  764                  return (IDMAP_ERR_ARG);
 763  765  
 764  766          zs = idmap_get_zone_specific(zone);
 765  767  
 766  768          if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid)
 767  769              == IDMAP_SUCCESS) {
 768  770                  return (IDMAP_SUCCESS);
 769  771          }
 770  772  
 771  773          bzero(&mapping, sizeof (idmap_mapping));
 772  774          mapping.id1.idtype = IDMAP_GID;
 773  775          mapping.id1.idmap_id_u.uid = gid;
 774  776          mapping.id2.idtype = IDMAP_SID;
 775  777  
 776  778          bzero(&results, sizeof (idmap_ids_res));
 777  779  
 778  780          args.idmap_mapping_batch_len = 1;
 779  781          args.idmap_mapping_batch_val = &mapping;
 780  782  
 781  783          if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
 782  784              (caddr_t)&args, xdr_idmap_ids_res,
 783  785              (caddr_t)&results) == 0) {
 784  786                  /* Door call succeded */
 785  787                  if (results.retcode != IDMAP_SUCCESS) {
 786  788                          status = results.retcode;
 787  789                          *rid = 0;
 788  790                          *sid_prefix = NULL;
 789  791                  } else if (results.ids.ids_len >= 1 &&
 790  792                      (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
 791  793                      results.ids.ids_val[0].id.idtype == IDMAP_USID ||
 792  794                      results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
 793  795                          status = results.ids.ids_val[0].retcode;
 794  796                          id = &results.ids.ids_val[0].id;
 795  797                          *sid_prefix = kidmap_find_sid_prefix(
 796  798                              id->idmap_id_u.sid.prefix);
 797  799                          *rid = id->idmap_id_u.sid.rid;
 798  800                          if (status == IDMAP_SUCCESS) {
 799  801                                  kidmap_cache_add_sid2gid(&zs->cache,
 800  802                                      *sid_prefix, *rid, gid,
 801  803                                      results.ids.ids_val[0].direction);
 802  804                          }
 803  805                  } else {
 804  806                          status = IDMAP_ERR_NOMAPPING;
 805  807                          *rid = 0;
 806  808                          *sid_prefix = NULL;
 807  809                  }
 808  810                  xdr_free(xdr_idmap_ids_res, (char *)&results);
 809  811          } else {
 810  812                  /* Door call failed */
 811  813                  status = IDMAP_ERR_NOMAPPING;
 812  814                  *rid = 0;
 813  815                  *sid_prefix = NULL;
 814  816          }
 815  817          return (status);
 816  818  }
 817  819  
 818  820  /*
 819  821   * Create handle to get SID to UID/GID mapping entries
 820  822   *
 821  823   * Input:
 822  824   *      none
 823  825   * Return:
 824  826   *      get_handle
 825  827   *
 826  828   */
 827  829  idmap_get_handle_t *
 828  830  kidmap_get_create(zone_t *zone)
 829  831  {
 830  832          idmap_zone_specific_t   *zs;
 831  833          idmap_get_handle_t      *handle;
 832  834  #define INIT_MAPPING_SIZE       32
 833  835  
 834  836          zs = idmap_get_zone_specific(zone);
 835  837  
 836  838          handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP);
 837  839  
 838  840          handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) *
 839  841              INIT_MAPPING_SIZE, KM_SLEEP);
 840  842  
 841  843          handle->result = kmem_zalloc((sizeof (idmap_get_res)) *
 842  844              INIT_MAPPING_SIZE, KM_SLEEP);
 843  845          handle->mapping_size = INIT_MAPPING_SIZE;
 844  846          handle->zs = zs;
 845  847  
 846  848          return (handle);
 847  849  }
 848  850  
 849  851  /*
 850  852   * Internal routine to extend a "get_handle"
 851  853   */
 852  854  static void
 853  855  kidmap_get_extend(idmap_get_handle_t *get_handle)
 854  856  {
 855  857          idmap_mapping *mapping;
 856  858          idmap_get_res *result;
 857  859          int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE;
 858  860  
 859  861          mapping = kmem_zalloc((sizeof (idmap_mapping)) *
 860  862              new_size, KM_SLEEP);
 861  863          (void) memcpy(mapping, get_handle->mapping,
 862  864              (sizeof (idmap_mapping)) * get_handle->mapping_size);
 863  865  
 864  866          result = kmem_zalloc((sizeof (idmap_get_res)) *
 865  867              new_size, KM_SLEEP);
 866  868          (void) memcpy(result, get_handle->result,
 867  869              (sizeof (idmap_get_res)) * get_handle->mapping_size);
 868  870  
 869  871          kmem_free(get_handle->mapping,
 870  872              (sizeof (idmap_mapping)) * get_handle->mapping_size);
 871  873          get_handle->mapping = mapping;
 872  874  
 873  875          kmem_free(get_handle->result,
 874  876              (sizeof (idmap_get_res)) * get_handle->mapping_size);
 875  877          get_handle->result = result;
 876  878  
 877  879          get_handle->mapping_size = new_size;
 878  880  }
 879  881  
 880  882  
 881  883  /*
 882  884   * Given Domain SID and RID, get UID
 883  885   *
 884  886   * Input:
 885  887   * sid_prefix   - Domain SID in canonical form
 886  888   * rid  - RID
 887  889   *
 888  890   * Output:
 889  891   * stat - status of the get request
 890  892   * uid  - POSIX UID if stat == IDMAP_SUCCESS
 891  893   *
 892  894   * Notes:
 893  895   * The output parameters will be set by idmap_get_mappings()
 894  896   * The sid_prefix is copied.
 895  897   */
 896  898  idmap_stat
 897  899  kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
 898  900      uint32_t rid, uid_t *uid, idmap_stat *stat)
 899  901  {
 900  902          idmap_mapping   *mapping;
 901  903          idmap_get_res   *result;
 902  904  
 903  905          if (get_handle == NULL || sid_prefix == NULL ||
 904  906              uid == NULL || stat == NULL)
 905  907                  return (IDMAP_ERR_ARG);
 906  908  
 907  909          if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix,
 908  910              rid, uid) == IDMAP_SUCCESS) {
 909  911                  *stat = IDMAP_SUCCESS;
 910  912                  return (IDMAP_SUCCESS);
 911  913          }
 912  914  
 913  915          /* Get a copy of sid_prefix */
 914  916          sid_prefix = kidmap_find_sid_prefix(sid_prefix);
 915  917  
 916  918          if (get_handle->mapping_num >= get_handle->mapping_size)
 917  919                  kidmap_get_extend(get_handle);
 918  920  
 919  921          mapping = &get_handle->mapping[get_handle->mapping_num];
 920  922          mapping->flag = 0;
 921  923          mapping->id1.idtype = IDMAP_SID;
 922  924          mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
 923  925          mapping->id1.idmap_id_u.sid.rid = rid;
 924  926          mapping->id2.idtype = IDMAP_UID;
 925  927  
 926  928          result = &get_handle->result[get_handle->mapping_num];
 927  929          result->idtype = IDMAP_UID;
 928  930          result->uid = uid;
 929  931          result->gid = NULL;
 930  932          result->pid = NULL;
 931  933          result->sid_prefix = NULL;
 932  934          result->rid = NULL;
 933  935          result->is_user = NULL;
 934  936          result->stat = stat;
 935  937  
 936  938          get_handle->mapping_num++;
 937  939  
 938  940          return (IDMAP_SUCCESS);
 939  941  }
 940  942  
 941  943  
 942  944  /*
 943  945   * Given Domain SID and RID, get GID
 944  946   *
 945  947   * Input:
 946  948   * sid_prefix   - Domain SID in canonical form
 947  949   * rid  - RID
 948  950   *
 949  951   * Output:
 950  952   * stat - status of the get request
 951  953   * gid  - POSIX GID if stat == IDMAP_SUCCESS
 952  954   *
 953  955   * Notes:
 954  956   * The output parameters will be set by idmap_get_mappings()
 955  957   * The sid_prefix is copied.
 956  958   */
 957  959  idmap_stat
 958  960  kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
 959  961      uint32_t rid, uid_t *gid, idmap_stat *stat)
 960  962  {
 961  963          idmap_mapping   *mapping;
 962  964          idmap_get_res   *result;
 963  965  
 964  966          if (get_handle == NULL || sid_prefix == NULL ||
 965  967              gid == NULL || stat == NULL)
 966  968                  return (IDMAP_ERR_ARG);
 967  969  
 968  970          if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix,
 969  971              rid, gid) == IDMAP_SUCCESS) {
 970  972                  *stat = IDMAP_SUCCESS;
 971  973                  return (IDMAP_SUCCESS);
 972  974          }
 973  975  
 974  976          /* Get a copy of sid_prefix */
 975  977          sid_prefix = kidmap_find_sid_prefix(sid_prefix);
 976  978  
 977  979          if (get_handle->mapping_num >= get_handle->mapping_size)
 978  980                  kidmap_get_extend(get_handle);
 979  981  
 980  982          mapping = &get_handle->mapping[get_handle->mapping_num];
 981  983          mapping->flag = 0;
 982  984          mapping->id1.idtype = IDMAP_SID;
 983  985          mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
 984  986          mapping->id1.idmap_id_u.sid.rid = rid;
 985  987          mapping->id2.idtype = IDMAP_GID;
 986  988  
 987  989          result = &get_handle->result[get_handle->mapping_num];
 988  990          result->idtype = IDMAP_GID;
 989  991          result->uid = NULL;
 990  992          result->gid = gid;
 991  993          result->pid = NULL;
 992  994          result->sid_prefix = NULL;
 993  995          result->rid = NULL;
 994  996          result->is_user = NULL;
 995  997          result->stat = stat;
 996  998  
 997  999          get_handle->mapping_num++;
 998 1000  
 999 1001          return (IDMAP_SUCCESS);
1000 1002  }
1001 1003  
1002 1004  
1003 1005  /*
1004 1006   * Given Domain SID and RID, get Posix ID
1005 1007   *
1006 1008   * Input:
1007 1009   * sid_prefix   - Domain SID in canonical form
1008 1010   * rid  - RID
1009 1011   *
1010 1012   * Output:
1011 1013   * stat    - status of the get request
1012 1014   * is_user - user or group
1013 1015   * pid     - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
1014 1016   *           POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
1015 1017   *
1016 1018   * Notes:
1017 1019   * The output parameters will be set by idmap_get_mappings()
1018 1020   * The sid_prefix is copied.
1019 1021   */
1020 1022  idmap_stat
1021 1023  kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
1022 1024      uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat)
1023 1025  {
1024 1026          idmap_mapping   *mapping;
1025 1027          idmap_get_res   *result;
1026 1028  
1027 1029          if (get_handle == NULL || sid_prefix == NULL || pid == NULL ||
1028 1030              is_user == NULL || stat == NULL)
1029 1031                  return (IDMAP_ERR_ARG);
1030 1032  
1031 1033          if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix,
1032 1034              rid, pid, is_user) == IDMAP_SUCCESS) {
1033 1035                  *stat = IDMAP_SUCCESS;
1034 1036                  return (IDMAP_SUCCESS);
1035 1037          }
1036 1038  
1037 1039          /* Get a copy of sid_prefix */
1038 1040          sid_prefix = kidmap_find_sid_prefix(sid_prefix);
1039 1041  
1040 1042          if (get_handle->mapping_num >= get_handle->mapping_size)
1041 1043                  kidmap_get_extend(get_handle);
1042 1044  
1043 1045          mapping = &get_handle->mapping[get_handle->mapping_num];
1044 1046          mapping->flag = 0;
1045 1047          mapping->id1.idtype = IDMAP_SID;
1046 1048          mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
1047 1049          mapping->id1.idmap_id_u.sid.rid = rid;
1048 1050          mapping->id2.idtype = IDMAP_POSIXID;
1049 1051  
1050 1052          result = &get_handle->result[get_handle->mapping_num];
1051 1053          result->idtype = IDMAP_POSIXID;
1052 1054          result->uid = NULL;
1053 1055          result->gid = NULL;
1054 1056          result->pid = pid;
1055 1057          result->sid_prefix = NULL;
1056 1058          result->rid = NULL;
1057 1059          result->is_user = is_user;
1058 1060          result->stat = stat;
1059 1061  
1060 1062          get_handle->mapping_num++;
1061 1063  
1062 1064          return (IDMAP_SUCCESS);
1063 1065  }
1064 1066  
1065 1067  
1066 1068  /*
1067 1069   * Given UID, get SID and RID
1068 1070   *
1069 1071   * Input:
1070 1072   * uid  - POSIX UID
1071 1073   *
1072 1074   * Output:
1073 1075   * stat - status of the get request
1074 1076   * sid  - SID in canonical form (if stat == IDMAP_SUCCESS)
1075 1077   * rid  - RID (if stat == IDMAP_SUCCESS)
1076 1078   *
1077 1079   * Note: The output parameters will be set by idmap_get_mappings()
1078 1080   */
1079 1081  idmap_stat
1080 1082  kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
1081 1083      const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1082 1084  {
1083 1085          idmap_mapping   *mapping;
1084 1086          idmap_get_res   *result;
1085 1087  
1086 1088          if (get_handle == NULL || sid_prefix == NULL ||
1087 1089              rid == NULL || stat == NULL)
1088 1090                  return (IDMAP_ERR_ARG);
1089 1091  
1090 1092          if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache,
1091 1093              sid_prefix, rid, uid) == IDMAP_SUCCESS) {
1092 1094                  *stat = IDMAP_SUCCESS;
1093 1095                  return (IDMAP_SUCCESS);
1094 1096          }
1095 1097  
1096 1098          if (get_handle->mapping_num >= get_handle->mapping_size)
1097 1099                  kidmap_get_extend(get_handle);
1098 1100  
1099 1101          mapping = &get_handle->mapping[get_handle->mapping_num];
1100 1102          mapping->flag = 0;
1101 1103          mapping->id1.idtype = IDMAP_UID;
1102 1104          mapping->id1.idmap_id_u.uid = uid;
1103 1105          mapping->id2.idtype = IDMAP_SID;
1104 1106  
1105 1107          result = &get_handle->result[get_handle->mapping_num];
1106 1108          result->idtype = IDMAP_SID;
1107 1109          result->uid = NULL;
1108 1110          result->gid = NULL;
1109 1111          result->pid = NULL;
1110 1112          result->sid_prefix = sid_prefix;
1111 1113          result->rid = rid;
1112 1114          result->is_user = NULL;
1113 1115          result->stat = stat;
1114 1116  
1115 1117          get_handle->mapping_num++;
1116 1118  
1117 1119          return (IDMAP_SUCCESS);
1118 1120  }
1119 1121  
1120 1122  
1121 1123  /*
1122 1124   * Given GID, get SID and RID
1123 1125   *
1124 1126   * Input:
1125 1127   * gid  - POSIX GID
1126 1128   *
1127 1129   * Output:
1128 1130   * stat - status of the get request
1129 1131   * sid  - SID in canonical form (if stat == IDMAP_SUCCESS)
1130 1132   * rid  - RID (if stat == IDMAP_SUCCESS)
1131 1133   *
1132 1134   * Note: The output parameters will be set by idmap_get_mappings()
1133 1135   */
1134 1136  idmap_stat
1135 1137  kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
1136 1138      const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1137 1139  {
1138 1140          idmap_mapping   *mapping;
1139 1141          idmap_get_res   *result;
1140 1142  
1141 1143          if (get_handle == NULL || sid_prefix == NULL ||
1142 1144              rid == NULL || stat == NULL)
1143 1145                  return (IDMAP_ERR_ARG);
1144 1146  
1145 1147          if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache,
1146 1148              sid_prefix, rid, gid) == IDMAP_SUCCESS) {
1147 1149                  *stat = IDMAP_SUCCESS;
1148 1150                  return (IDMAP_SUCCESS);
1149 1151          }
1150 1152  
1151 1153          if (get_handle->mapping_num >= get_handle->mapping_size)
1152 1154                  kidmap_get_extend(get_handle);
1153 1155  
1154 1156          mapping = &get_handle->mapping[get_handle->mapping_num];
1155 1157          mapping->flag = 0;
1156 1158          mapping->id1.idtype = IDMAP_GID;
1157 1159          mapping->id1.idmap_id_u.gid = gid;
1158 1160          mapping->id2.idtype = IDMAP_SID;
1159 1161  
1160 1162          result = &get_handle->result[get_handle->mapping_num];
1161 1163          result->idtype = IDMAP_SID;
1162 1164          result->uid = NULL;
1163 1165          result->gid = NULL;
1164 1166          result->pid = NULL;
1165 1167          result->sid_prefix = sid_prefix;
1166 1168          result->rid = rid;
1167 1169          result->is_user = NULL;
1168 1170          result->stat = stat;
1169 1171  
1170 1172          get_handle->mapping_num++;
1171 1173  
1172 1174          return (IDMAP_SUCCESS);
1173 1175  }
1174 1176  
1175 1177  
1176 1178  /*
1177 1179   * Process the batched "get mapping" requests. The results (i.e.
1178 1180   * status and identity) will be available in the data areas
1179 1181   * provided by individual requests.
1180 1182   *
1181 1183   * If the door call fails the status IDMAP_ERR_NOMAPPING is
1182 1184   * return and the UID or UID result is set to "nobody"
1183 1185   */
1184 1186  
1185 1187  idmap_stat
1186 1188  kidmap_get_mappings(idmap_get_handle_t *get_handle)
1187 1189  {
1188 1190          idmap_mapping_batch     rpc_args;
1189 1191          idmap_ids_res           rpc_res;
1190 1192          uint32_t                op = IDMAP_GET_MAPPED_IDS;
1191 1193          idmap_mapping           *request;
1192 1194          idmap_get_res           *result;
1193 1195          idmap_id                *id;
1194 1196          int                     status;
1195 1197          int                     i;
1196 1198          const char              *sid_prefix;
1197 1199          int                     is_user;
1198 1200          idmap_cache_t           *cache;
1199 1201          int                     direction;
1200 1202  
1201 1203          if (get_handle == NULL)
1202 1204                  return (IDMAP_ERR_ARG);
1203 1205  
1204 1206          if (get_handle->mapping_num == 0)
1205 1207                  return (IDMAP_SUCCESS);
1206 1208          cache = &get_handle->zs->cache;
1207 1209  
1208 1210          bzero(&rpc_res, sizeof (idmap_ids_res));
1209 1211  
1210 1212          rpc_args.idmap_mapping_batch_len = get_handle->mapping_num;
1211 1213          rpc_args.idmap_mapping_batch_val = get_handle->mapping;
1212 1214  
1213 1215          if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch,
1214 1216              (caddr_t)&rpc_args, xdr_idmap_ids_res,
1215 1217              (caddr_t)&rpc_res) != 0) {
1216 1218                  /* Door call failed */
1217 1219                  status = IDMAP_ERR_NOMAPPING;
1218 1220                  goto error;
1219 1221          }
1220 1222  
1221 1223          status = rpc_res.retcode;
1222 1224          if (status != IDMAP_SUCCESS) {
1223 1225                  /* RPC returned idmap error code */
1224 1226                  xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1225 1227                  goto error;
1226 1228          }
1227 1229  
1228 1230          for (i = 0; i < get_handle->mapping_num; i++) {
1229 1231                  request = &get_handle->mapping[i];
1230 1232                  result =  &get_handle->result[i];
1231 1233  
1232 1234                  if (i >= rpc_res.ids.ids_len) {
1233 1235                          *result->stat = IDMAP_ERR_NOMAPPING;
1234 1236                          if (result->uid)
1235 1237                                  *result->uid = UID_NOBODY;
1236 1238                          if (result->gid)
1237 1239                                  *result->gid = GID_NOBODY;
1238 1240                          if (result->pid)
1239 1241                                  *result->pid = UID_NOBODY;
1240 1242                          if (result->is_user)
1241 1243                                  *result->is_user = 1;
1242 1244                          if (result->sid_prefix)
1243 1245                                  *result->sid_prefix = NULL;
1244 1246                          if (result->rid)
1245 1247                                  *result->rid = 0;
1246 1248                          continue;
1247 1249                  }
1248 1250  
1249 1251                  *result->stat = rpc_res.ids.ids_val[i].retcode;
1250 1252  
1251 1253                  id = &rpc_res.ids.ids_val[i].id;
1252 1254                  direction = rpc_res.ids.ids_val[i].direction;
1253 1255  
1254 1256                  switch (id->idtype) {
1255 1257                  case IDMAP_UID:
1256 1258                          if (result->uid)
1257 1259                                  *result->uid = id->idmap_id_u.uid;
1258 1260                          if (result->pid)
1259 1261                                  *result->pid = id->idmap_id_u.uid;
1260 1262                          if (result->is_user)
1261 1263                                  *result->is_user = 1;
1262 1264                          sid_prefix = kidmap_find_sid_prefix(
1263 1265                              request->id1.idmap_id_u.sid.prefix);
1264 1266                          if (*result->stat == IDMAP_SUCCESS && result->uid)
1265 1267                                  kidmap_cache_add_sid2uid(
1266 1268                                      cache, sid_prefix,
1267 1269                                      request->id1.idmap_id_u.sid.rid,
1268 1270                                      id->idmap_id_u.uid,
1269 1271                                      direction);
1270 1272                          else if (*result->stat == IDMAP_SUCCESS && result->pid)
1271 1273                                  kidmap_cache_add_sid2pid(
1272 1274                                      cache, sid_prefix,
1273 1275                                      request->id1.idmap_id_u.sid.rid,
1274 1276                                      id->idmap_id_u.uid, 1,
1275 1277                                      direction);
1276 1278                          break;
1277 1279  
1278 1280                  case IDMAP_GID:
1279 1281                          if (result->gid)
1280 1282                                  *result->gid = id->idmap_id_u.gid;
1281 1283                          if (result->pid)
1282 1284                                  *result->pid = id->idmap_id_u.gid;
1283 1285                          if (result->is_user)
1284 1286                                  *result->is_user = 0;
1285 1287                          sid_prefix = kidmap_find_sid_prefix(
1286 1288                              request->id1.idmap_id_u.sid.prefix);
1287 1289                          if (*result->stat == IDMAP_SUCCESS && result->gid)
1288 1290                                  kidmap_cache_add_sid2gid(
1289 1291                                      cache, sid_prefix,
1290 1292                                      request->id1.idmap_id_u.sid.rid,
1291 1293                                      id->idmap_id_u.gid,
1292 1294                                      direction);
1293 1295                          else if (*result->stat == IDMAP_SUCCESS && result->pid)
1294 1296                                  kidmap_cache_add_sid2pid(
1295 1297                                      cache, sid_prefix,
1296 1298                                      request->id1.idmap_id_u.sid.rid,
1297 1299                                      id->idmap_id_u.gid, 0,
1298 1300                                      direction);
1299 1301                          break;
  
    | 
      ↓ open down ↓ | 
    1265 lines elided | 
    
      ↑ open up ↑ | 
  
1300 1302  
1301 1303                  case IDMAP_SID:
1302 1304                  case IDMAP_USID:
1303 1305                  case IDMAP_GSID:
1304 1306                          sid_prefix = kidmap_find_sid_prefix(
1305 1307                              id->idmap_id_u.sid.prefix);
1306 1308                          if (result->sid_prefix && result->rid) {
1307 1309                                  *result->sid_prefix = sid_prefix;
1308 1310                                  *result->rid = id->idmap_id_u.sid.rid;
1309 1311                          }
     1312 +                        if (*result->stat == IDMAP_ERR_NOTFOUND &&
     1313 +                            sid_prefix != NULL) {
     1314 +                                /* IDMAP generated a local SID. Use it. */
     1315 +                                *result->stat = IDMAP_SUCCESS;
     1316 +                        }
     1317 +
1310 1318                          if (*result->stat == IDMAP_SUCCESS &&
1311 1319                              request->id1.idtype == IDMAP_UID)
1312 1320                                  kidmap_cache_add_sid2uid(
1313 1321                                      cache, sid_prefix,
1314 1322                                      id->idmap_id_u.sid.rid,
1315 1323                                      request->id1.idmap_id_u.uid,
1316 1324                                      direction);
1317 1325                          else if (*result->stat == IDMAP_SUCCESS &&
1318 1326                              request->id1.idtype == IDMAP_GID)
1319 1327                                  kidmap_cache_add_sid2gid(
1320 1328                                      cache, sid_prefix,
1321 1329                                      id->idmap_id_u.sid.rid,
1322 1330                                      request->id1.idmap_id_u.gid,
1323 1331                                      direction);
1324 1332                          break;
1325 1333  
1326 1334                  default:
1327 1335                          *result->stat = IDMAP_ERR_NORESULT;
1328 1336                          if (result->uid)
1329 1337                                  *result->uid = UID_NOBODY;
1330 1338                          if (result->gid)
1331 1339                                  *result->gid = GID_NOBODY;
1332 1340                          if (result->pid)
1333 1341                                  *result->pid = UID_NOBODY;
1334 1342                          if (result->is_user)
1335 1343                                  *result->is_user = 1;
1336 1344                          if (result->sid_prefix)
1337 1345                                  *result->sid_prefix = NULL;
1338 1346                          if (result->rid)
1339 1347                                  *result->rid = 0;
1340 1348                          break;
1341 1349                  }
1342 1350          }
1343 1351          xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1344 1352  
1345 1353          /* Reset get_handle for new resquests */
1346 1354          get_handle->mapping_num = 0;
1347 1355          return (status);
1348 1356  
1349 1357  error:
1350 1358          for (i = 0; i < get_handle->mapping_num; i++) {
1351 1359                  result =  &get_handle->result[i];
1352 1360  
1353 1361                  *result->stat = status;
1354 1362                  if (result->uid)
1355 1363                          *result->uid = UID_NOBODY;
1356 1364                  if (result->gid)
1357 1365                          *result->gid = GID_NOBODY;
1358 1366                  if (result->pid)
1359 1367                          *result->pid = UID_NOBODY;
1360 1368                  if (result->is_user)
1361 1369                          *result->is_user = 1;
1362 1370                  if (result->sid_prefix)
1363 1371                          *result->sid_prefix = NULL;
1364 1372                  if (result->rid)
1365 1373                          *result->rid = 0;
1366 1374          }
1367 1375  
1368 1376          /* Reset get_handle for new resquests */
1369 1377          get_handle->mapping_num = 0;
1370 1378          return (status);
1371 1379  }
1372 1380  
1373 1381  
1374 1382  /*
1375 1383   * Destroy the "get mapping" handle
1376 1384   */
1377 1385  void
1378 1386  kidmap_get_destroy(idmap_get_handle_t *get_handle)
1379 1387  {
1380 1388          if (get_handle == NULL)
1381 1389                  return;
1382 1390  
1383 1391          kmem_free(get_handle->mapping,
1384 1392              (sizeof (idmap_mapping)) * get_handle->mapping_size);
1385 1393          get_handle->mapping = NULL;
1386 1394  
1387 1395          kmem_free(get_handle->result,
1388 1396              (sizeof (idmap_get_res)) * get_handle->mapping_size);
1389 1397          get_handle->result = NULL;
1390 1398  
1391 1399          kmem_free(get_handle, sizeof (idmap_get_handle_t));
1392 1400  }
1393 1401  
1394 1402  
1395 1403  static int
1396 1404  kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args,
1397 1405      caddr_t args, xdrproc_t xdr_res, caddr_t res)
1398 1406  {
1399 1407          XDR             xdr_ctx;
1400 1408          struct  rpc_msg reply_msg;
1401 1409          char            *inbuf_ptr = NULL;
1402 1410          size_t          inbuf_size = 4096;
1403 1411          char            *outbuf_ptr = NULL;
1404 1412          size_t          outbuf_size = 4096;
1405 1413          size_t          size;
1406 1414          int             status = 0;
1407 1415          door_arg_t      params;
1408 1416          int             retry = 0;
1409 1417          struct rpc_msg  call_msg;
1410 1418  
1411 1419          params.rbuf = NULL;
1412 1420          params.rsize = 0;
1413 1421  
1414 1422  retry:
1415 1423          inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP);
1416 1424          outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP);
1417 1425  
1418 1426          xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE);
1419 1427  
1420 1428          call_msg.rm_call.cb_prog = IDMAP_PROG;
1421 1429          call_msg.rm_call.cb_vers = IDMAP_V1;
1422 1430          call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id);
1423 1431  
1424 1432          if (!xdr_callhdr(&xdr_ctx, &call_msg)) {
1425 1433  #ifdef  DEBUG
1426 1434                  zcmn_err(zs->zone_id, CE_WARN,
1427 1435                      "idmap: xdr encoding header error");
1428 1436  #endif  /* DEBUG */
1429 1437                  status = -1;
1430 1438                  goto exit;
1431 1439          }
1432 1440  
1433 1441          if (!xdr_uint32(&xdr_ctx, &op) ||
1434 1442              /* Auth none */
1435 1443              !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1436 1444              !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1437 1445              /* RPC args */
1438 1446              !xdr_args(&xdr_ctx, args)) {
1439 1447  #ifdef  DEBUG
1440 1448                  zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error");
1441 1449  #endif  /* DEBUG */
1442 1450                  if (retry > 2) {
1443 1451                          status = -1;
1444 1452                          goto exit;
1445 1453                  }
1446 1454                  retry++;
1447 1455                  if (inbuf_ptr) {
1448 1456                          kmem_free(inbuf_ptr, inbuf_size);
1449 1457                          inbuf_ptr = NULL;
1450 1458                  }
1451 1459                  if (outbuf_ptr) {
1452 1460                          kmem_free(outbuf_ptr, outbuf_size);
1453 1461                          outbuf_ptr = NULL;
1454 1462                  }
1455 1463                  if ((size = xdr_sizeof(xdr_args, args)) == 0) {
1456 1464  #ifdef  DEBUG
1457 1465                          zcmn_err(zs->zone_id, CE_WARN,
1458 1466                              "idmap: xdr_sizeof error");
1459 1467  #endif  /* DEBUG */
1460 1468                          status = -1;
1461 1469                          goto exit;
1462 1470                  }
1463 1471                  inbuf_size = size + 1024;
1464 1472                  outbuf_size = size + 1024;
1465 1473                  goto retry;
1466 1474          }
1467 1475  
1468 1476          params.data_ptr = inbuf_ptr;
1469 1477          params.data_size = XDR_GETPOS(&xdr_ctx);
1470 1478          params.desc_ptr = NULL;
1471 1479          params.desc_num = 0;
1472 1480          params.rbuf = outbuf_ptr;
1473 1481          params.rsize = outbuf_size;
1474 1482  
1475 1483          if (kidmap_call_door(zs, ¶ms) != 0) {
1476 1484                  status = -1;
1477 1485                  goto exit;
1478 1486          }
1479 1487  
1480 1488          reply_msg.acpted_rply.ar_verf = _null_auth;
1481 1489          reply_msg.acpted_rply.ar_results.where = res;
1482 1490          reply_msg.acpted_rply.ar_results.proc = xdr_res;
1483 1491          xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE);
1484 1492          if (xdr_replymsg(&xdr_ctx, &reply_msg)) {
1485 1493                  if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED ||
1486 1494                      reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
1487 1495                          status = -1;
1488 1496                          goto exit;
1489 1497                  }
1490 1498          } else {
1491 1499  #ifdef  DEBUG
1492 1500                  zcmn_err(zs->zone_id, CE_WARN,
1493 1501                      "idmap: xdr decoding reply message error");
1494 1502  #endif  /* DEBUG */
1495 1503                  status = -1;
1496 1504          }
1497 1505  
1498 1506  exit:
1499 1507          if (outbuf_ptr != params.rbuf && params.rbuf != NULL)
1500 1508                  kmem_free(params.rbuf, params.rsize);
1501 1509          if (inbuf_ptr)
1502 1510                  kmem_free(inbuf_ptr, inbuf_size);
1503 1511          if (outbuf_ptr)
1504 1512                  kmem_free(outbuf_ptr, outbuf_size);
1505 1513          return (status);
1506 1514  }
  
    | 
      ↓ open down ↓ | 
    187 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX