Print this page
    
First attempt at further IPsec cluster cleanup
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/inet/ip/ip_sadb.c
          +++ new/usr/src/uts/common/inet/ip/ip_sadb.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.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  #include <sys/types.h>
  27   27  #include <sys/stream.h>
  28   28  #include <sys/strsubr.h>
  29   29  #include <sys/sunddi.h>
  30   30  #include <sys/ddi.h>
  31   31  #include <sys/strlog.h>
  32   32  
  33   33  #include <inet/common.h>
  34   34  #include <inet/mib2.h>
  35   35  #include <inet/ip.h>
  36   36  #include <inet/ip6.h>
  37   37  
  38   38  #include <net/pfkeyv2.h>
  39   39  #include <inet/sadb.h>
  40   40  #include <inet/ipsec_impl.h>
  41   41  #include <inet/ipdrop.h>
  42   42  #include <inet/ipsecesp.h>
  43   43  #include <inet/ipsecah.h>
  44   44  #include <sys/kstat.h>
  45   45  
  46   46  /*
  47   47   * Returns B_TRUE if the identities in the SA match the identities
  48   48   * in the "latch" structure.
  49   49   */
  50   50  
  51   51  static boolean_t
  52   52  ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa)
  53   53  {
  54   54          ASSERT(ipl->ipl_ids_latched == B_TRUE);
  55   55          return ipsid_equal(ipl->ipl_local_cid, sa->ipsa_src_cid) &&
  56   56              ipsid_equal(ipl->ipl_remote_cid, sa->ipsa_dst_cid);
  57   57  }
  58   58  
  59   59  /* l1 is packet label; l2 is SA label */
  60   60  boolean_t
  61   61  ipsec_label_match(ts_label_t *l1, ts_label_t *l2)
  62   62  {
  63   63          if (!is_system_labeled())
  64   64                  return (B_TRUE);
  65   65  
  66   66          /*
  67   67           * Check for NULL label.  Unlabeled SA (l2) always matches;
  68   68           * unlabeled user with labeled  SA always fails
  69   69           */
  70   70          if (l2 == NULL)
  71   71                  return (B_TRUE);
  72   72  
  73   73          if (l1 == NULL)
  74   74                  return (B_FALSE);
  75   75  
  76   76          /* Simple IPsec MLS policy: labels must be equal */
  77   77          /* In future will need bit in policy saying whether this is the case */
  78   78  
  79   79          /*
  80   80           * label_equal() checks DOI and label contents.  We should be
  81   81           * good to go with this check.
  82   82           */
  83   83          return (label_equal(l1, l2));
  84   84  }
  85   85  
  86   86  
  87   87  /*
  88   88   * Look up a security association based on the unique ID generated by IP and
  89   89   * transport or tunnel information, such as ports and upper-layer protocol,
  90   90   * and the inner and outer address(es).  Used for uniqueness testing and
  91   91   * outbound packets.  The outer source address may be ignored.
  92   92   *
  93   93   * I expect an SA hash bucket, and that its per-bucket mutex is held.
  94   94   * The SA ptr I return will have its reference count incremented by one.
  95   95   */
  96   96  ipsa_t *
  97   97  ipsec_getassocbyconn(isaf_t *bucket, ip_xmit_attr_t *ixa, uint32_t *src,
  98   98      uint32_t *dst, sa_family_t af, uint8_t protocol, ts_label_t *tsl)
  99   99  {
 100  100          ipsa_t *retval, *candidate;
 101  101          ipsec_action_t *candact;
 102  102          boolean_t need_unique;
 103  103          boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL);
 104  104          uint64_t unique_id;
 105  105          uint32_t old_flags, excludeflags;
 106  106          ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
 107  107          ipsec_action_t *actlist = ixa->ixa_ipsec_action;
 108  108          ipsec_action_t *act;
 109  109          ipsec_latch_t *ipl = ixa->ixa_ipsec_latch;
 110  110          ipsa_ref_t *ipr = NULL;
 111  111          sa_family_t inaf = ixa->ixa_ipsec_inaf;
 112  112          uint32_t *insrc = ixa->ixa_ipsec_insrc;
 113  113          uint32_t *indst = ixa->ixa_ipsec_indst;
 114  114          uint8_t insrcpfx = ixa->ixa_ipsec_insrcpfx;
 115  115          uint8_t indstpfx = ixa->ixa_ipsec_indstpfx;
 116  116  
 117  117          ASSERT(MUTEX_HELD(&bucket->isaf_lock));
 118  118  
 119  119          /*
 120  120           * Caller must set ip_xmit_attr_t structure such that we know
 121  121           * whether this is tunnel mode or transport mode based on
 122  122           * IXAF_IPSEC_TUNNEL.  If this flag is set, we assume that
 123  123           * there are valid inner src and destination addresses to compare.
 124  124           */
 125  125  
 126  126          /*
 127  127           * Fast path: do we have a latch structure, is it for this bucket,
 128  128           * and does the generation number match?  If so, refhold and return.
 129  129           */
 130  130  
 131  131          if (ipl != NULL) {
 132  132                  ASSERT((protocol == IPPROTO_AH) || (protocol == IPPROTO_ESP));
 133  133                  ipr = &ixa->ixa_ipsec_ref[protocol - IPPROTO_ESP];
 134  134  
 135  135                  retval = ipr->ipsr_sa;
 136  136  
 137  137                  /*
 138  138                   * NOTE: The isaf_gen check (incremented upon
 139  139                   * sadb_unlinkassoc()) protects against retval being a freed
 140  140                   * SA.  (We're exploiting short-circuit evaluation.)
 141  141                   */
 142  142                  if ((bucket == ipr->ipsr_bucket) &&
 143  143                      (bucket->isaf_gen == ipr->ipsr_gen) &&
 144  144                      (retval->ipsa_state != IPSA_STATE_DEAD) &&
 145  145                      !(retval->ipsa_flags & IPSA_F_CINVALID)) {
 146  146                          IPSA_REFHOLD(retval);
 147  147                          return (retval);
 148  148                  }
 149  149          }
 150  150  
 151  151          ASSERT((pp != NULL) || (actlist != NULL));
 152  152          if (actlist == NULL)
 153  153                  actlist = pp->ipsp_act;
 154  154          ASSERT(actlist != NULL);
 155  155  
 156  156          need_unique = actlist->ipa_want_unique;
 157  157          unique_id = SA_FORM_UNIQUE_ID(ixa);
 158  158  
 159  159          /*
 160  160           * Precompute mask for SA flags comparison: If we need a
 161  161           * unique SA and an SA has already been used, or if the SA has
 162  162           * a unique value which doesn't match, we aren't interested in
 163  163           * the SA..
 164  164           */
 165  165  
 166  166          excludeflags = IPSA_F_UNIQUE;
 167  167          if (need_unique)
 168  168                  excludeflags |= IPSA_F_USED;
 169  169  
 170  170          /*
 171  171           * Walk the hash bucket, matching on:
 172  172           *
 173  173           * - unique_id
 174  174           * - destination
 175  175           * - source
 176  176           * - algorithms
 177  177           * - inner dst
 178  178           * - inner src
 179  179           * - <MORE TBD>
 180  180           *
 181  181           * Make sure that wildcard sources are inserted at the end of the hash
 182  182           * bucket.
 183  183           *
 184  184           * DEFINITIONS: A _shared_ SA is one with unique_id == 0 and USED.
 185  185           *              An _unused_ SA is one with unique_id == 0 and not USED.
 186  186           *              A _unique_ SA is one with unique_id != 0 and USED.
 187  187           *              An SA with unique_id != 0 and not USED never happens.
 188  188           */
 189  189  
 190  190          candidate = NULL;
 191  191  
 192  192          for (retval = bucket->isaf_ipsa; retval != NULL;
 193  193              retval = retval->ipsa_next) {
 194  194                  ASSERT((candidate == NULL) ||
 195  195                      MUTEX_HELD(&candidate->ipsa_lock));
 196  196  
 197  197                  /*
 198  198                   * Q: Should I lock this SA?
 199  199                   * A: For now, yes.  I change and use too many fields in here
 200  200                   *    (e.g. unique_id) that I may be racing with other threads.
 201  201                   *    Also, the refcnt needs to be bumped up.
 202  202                   */
 203  203  
 204  204                  mutex_enter(&retval->ipsa_lock);
 205  205  
 206  206                  /* My apologies for the use of goto instead of continue. */
 207  207  
 208  208                  /* Outer destination address */
 209  209                  if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af))
 210  210                          goto next_ipsa; /* Destination mismatch. */
 211  211  
 212  212                  /* Outer source address */
 213  213                  if (!IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) &&
 214  214                      !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af))
 215  215                          goto next_ipsa; /* Specific source and not matched. */
 216  216  
 217  217                  if (tunnel_mode) {
 218  218                          /* Check tunnel mode */
 219  219                          if (!(retval->ipsa_flags & IPSA_F_TUNNEL))
 220  220                                  goto next_ipsa; /* Not tunnel mode SA */
 221  221  
 222  222                          /* Inner destination address */
 223  223                          if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innerdst, inaf)) {
 224  224                                  if (!ip_addr_match((uint8_t *)indst,
 225  225                                      min(indstpfx, retval->ipsa_innerdstpfx),
 226  226                                      (in6_addr_t *)retval->ipsa_innerdst))
 227  227                                          goto next_ipsa; /* not matched. */
 228  228                          }
 229  229  
 230  230                          /* Inner source address */
 231  231                          if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innersrc, inaf)) {
 232  232                                  if (!ip_addr_match((uint8_t *)insrc,
 233  233                                      min(insrcpfx, retval->ipsa_innersrcpfx),
 234  234                                      (in6_addr_t *)retval->ipsa_innersrc))
 235  235                                          goto next_ipsa; /* not matched. */
 236  236                          }
 237  237                  } else {
 238  238                          /* Check transport mode */
 239  239                          if (retval->ipsa_flags & IPSA_F_TUNNEL)
 240  240                                  goto next_ipsa; /* Not transport mode SA */
 241  241  
 242  242                          /*
 243  243                           * TODO - If we ever do RFC 3884's dream of transport-
 244  244                           * mode SAs with inner IP address selectors, we need
 245  245                           * to put some code here.
 246  246                           */
 247  247                  }
 248  248  
 249  249                  /*
 250  250                   * XXX should be able to use cached/latched action
 251  251                   * to dodge this loop
 252  252                   */
 253  253                  for (act = actlist; act != NULL; act = act->ipa_next) {
 254  254                          ipsec_act_t *ap = &act->ipa_act;
 255  255                          if (ap->ipa_type != IPSEC_POLICY_APPLY)
 256  256                                  continue;
 257  257  
 258  258                          /*
 259  259                           * XXX ugly.  should be better way to do this test
 260  260                           */
 261  261                          if (protocol == IPPROTO_AH) {
 262  262                                  if (!(ap->ipa_apply.ipp_use_ah))
 263  263                                          continue;
 264  264                                  if (ap->ipa_apply.ipp_auth_alg !=
 265  265                                      retval->ipsa_auth_alg)
 266  266                                          continue;
 267  267                                  if (ap->ipa_apply.ipp_ah_minbits >
 268  268                                      retval->ipsa_authkeybits)
 269  269                                          continue;
 270  270                          } else {
 271  271                                  if (!(ap->ipa_apply.ipp_use_esp))
 272  272                                          continue;
 273  273  
 274  274                                  if ((ap->ipa_apply.ipp_encr_alg !=
 275  275                                      retval->ipsa_encr_alg))
 276  276                                          continue;
 277  277  
 278  278                                  if (ap->ipa_apply.ipp_espe_minbits >
 279  279                                      retval->ipsa_encrkeybits)
 280  280                                          continue;
 281  281  
 282  282                                  if (ap->ipa_apply.ipp_esp_auth_alg != 0) {
 283  283                                          if (ap->ipa_apply.ipp_esp_auth_alg !=
 284  284                                              retval->ipsa_auth_alg)
 285  285                                                  continue;
 286  286                                          if (ap->ipa_apply.ipp_espa_minbits >
 287  287                                              retval->ipsa_authkeybits)
 288  288                                                  continue;
 289  289                                  }
 290  290                          }
 291  291  
 292  292                          /*
 293  293                           * Check key mgmt proto, cookie
 294  294                           */
 295  295                          if ((ap->ipa_apply.ipp_km_proto != 0) &&
 296  296                              (retval->ipsa_kmp != 0) &&
 297  297                              (ap->ipa_apply.ipp_km_proto != retval->ipsa_kmp))
 298  298                                  continue;
 299  299  
 300  300                          if ((ap->ipa_apply.ipp_km_cookie != 0) &&
 301  301                              (retval->ipsa_kmc != 0) &&
 302  302                              (ap->ipa_apply.ipp_km_cookie != retval->ipsa_kmc))
 303  303                                  continue;
 304  304  
 305  305                          break;
 306  306                  }
 307  307                  if (act == NULL)
 308  308                          goto next_ipsa; /* nothing matched */
 309  309  
 310  310                  /*
 311  311                   * Do identities match?
 312  312                   */
 313  313                  if (ipl && ipl->ipl_ids_latched &&
 314  314                      !ipsec_match_outbound_ids(ipl, retval))
 315  315                          goto next_ipsa;
 316  316  
 317  317                  /*
 318  318                   * Do labels match?
 319  319                   */
 320  320                  if (!ipsec_label_match(tsl, retval->ipsa_tsl))
 321  321                          goto next_ipsa;
 322  322  
 323  323                  /*
 324  324                   * At this point, we know that we have at least a match on:
 325  325                   *
 326  326                   * - dest
 327  327                   * - source (if source is specified, i.e. non-zeroes)
 328  328                   * - inner dest (if specified)
 329  329                   * - inner source (if specified)
 330  330                   * - auth alg (if auth alg is specified, i.e. non-zero)
 331  331                   * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero)
 332  332                   * and we know that the SA keylengths are appropriate.
 333  333                   *
 334  334                   * (Keep in mind known-src SAs are hit before zero-src SAs,
 335  335                   * thanks to sadb_insertassoc().)
 336  336                   * If we need a unique asssociation, optimally we have
 337  337                   * ipsa_unique_id == unique_id, otherwise NOT USED
 338  338                   * is held in reserve (stored in candidate).
 339  339                   *
 340  340                   * For those stored in candidate, take best-match (i.e. given
 341  341                   * a choice, candidate should have non-zero ipsa_src).
 342  342                   */
 343  343  
 344  344                  /*
 345  345                   * If SA has a unique value which matches, we're all set...
 346  346                   * "key management knows best"
 347  347                   */
 348  348                  if ((retval->ipsa_flags & IPSA_F_UNIQUE) &&
 349  349                      ((unique_id & retval->ipsa_unique_mask) ==
 350  350                      retval->ipsa_unique_id))
 351  351                          break;
 352  352  
 353  353                  /*
 354  354                   * If we need a unique SA and this SA has already been used,
 355  355                   * or if the SA has a unique value which doesn't match,
 356  356                   * this isn't for us.
 357  357                   */
 358  358  
 359  359                  if (retval->ipsa_flags & excludeflags)
 360  360                          goto next_ipsa;
 361  361  
 362  362  
 363  363                  /*
 364  364                   * I found a candidate..
 365  365                   */
 366  366                  if (candidate == NULL) {
 367  367                          /*
 368  368                           * and didn't already have one..
 369  369                           */
 370  370                          candidate = retval;
 371  371                          candact = act;
 372  372                          continue;
 373  373                  } else {
 374  374                          /*
 375  375                           * If candidate's source address is zero and
 376  376                           * the current match (i.e. retval) address is
 377  377                           * not zero, we have a better candidate..
 378  378                           */
 379  379                          if (IPSA_IS_ADDR_UNSPEC(candidate->ipsa_srcaddr, af) &&
 380  380                              !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) {
 381  381                                  mutex_exit(&candidate->ipsa_lock);
 382  382                                  candidate = retval;
 383  383                                  candact = act;
 384  384                                  continue;
 385  385                          }
 386  386                  }
 387  387  next_ipsa:
 388  388                  mutex_exit(&retval->ipsa_lock);
 389  389          }
 390  390          ASSERT((retval == NULL) || MUTEX_HELD(&retval->ipsa_lock));
 391  391          ASSERT((candidate == NULL) || MUTEX_HELD(&candidate->ipsa_lock));
 392  392          ASSERT((retval == NULL) || (act != NULL));
 393  393          ASSERT((candidate == NULL) || (candact != NULL));
 394  394  
 395  395          /* Let caller react to a lookup failure when it gets NULL. */
 396  396          if (retval == NULL && candidate == NULL)
 397  397                  return (NULL);
 398  398  
 399  399          if (retval == NULL) {
 400  400                  ASSERT(MUTEX_HELD(&candidate->ipsa_lock));
 401  401                  retval = candidate;
 402  402                  act = candact;
 403  403          } else if (candidate != NULL) {
 404  404                  mutex_exit(&candidate->ipsa_lock);
 405  405          }
 406  406          ASSERT(MUTEX_HELD(&retval->ipsa_lock));
 407  407          ASSERT(act != NULL);
 408  408  
 409  409          /*
 410  410           * Even though I hold the mutex, since the reference counter is an
 411  411           * atomic operation, I really have to use the IPSA_REFHOLD macro.
 412  412           */
 413  413          IPSA_REFHOLD(retval);
 414  414  
 415  415          /*
 416  416           * This association is no longer unused.
 417  417           */
 418  418          old_flags = retval->ipsa_flags;
 419  419          retval->ipsa_flags |= IPSA_F_USED;
 420  420  
 421  421          /*
 422  422           * Cache a reference to this SA for the fast path.
 423  423           */
 424  424          if (ipr != NULL) {
 425  425                  ipr->ipsr_bucket = bucket;
 426  426                  ipr->ipsr_gen = bucket->isaf_gen;
 427  427                  ipr->ipsr_sa = retval;
 428  428                  /* I'm now caching, so the cache-invalid flag goes away! */
 429  429                  retval->ipsa_flags &= ~IPSA_F_CINVALID;
 430  430          }
 431  431          /*
 432  432           * Latch various things while we're here..
 433  433           */
 434  434          if (ipl != NULL) {
 435  435                  if (!ipl->ipl_ids_latched) {
 436  436                          ipsec_latch_ids(ipl,
 437  437                              retval->ipsa_src_cid, retval->ipsa_dst_cid);
 438  438                  }
 439  439                  if (ixa->ixa_ipsec_action == NULL) {
 440  440                          IPACT_REFHOLD(act);
 441  441                          ixa->ixa_ipsec_action = act;
 442  442                  }
 443  443          }
 444  444  
 445  445          /*
 446  446           * Set the uniqueness only first time.
 447  447           */
 448  448          if (need_unique && !(old_flags & IPSA_F_USED)) {
 449  449                  if (retval->ipsa_unique_id == 0) {
 450  450                          ASSERT((retval->ipsa_flags & IPSA_F_UNIQUE) == 0);
 451  451                          /*
 452  452                           * From now on, only this src, dst[ports, addr],
 453  453                           * proto, should use it.
 454  454                           */
 455  455                          retval->ipsa_flags |= IPSA_F_UNIQUE;
 456  456                          retval->ipsa_unique_id = unique_id;
 457  457                          retval->ipsa_unique_mask = SA_UNIQUE_MASK(
 458  458                              ixa->ixa_ipsec_src_port, ixa->ixa_ipsec_dst_port,
 459  459                              protocol, 0);
 460  460                  }
 461  461  
 462  462                  /*
 463  463                   * Set the source address and adjust the hash
 464  464                   * buckets only if src_addr is zero.
 465  465                   */
 466  466                  if (IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) {
 467  467                          /*
 468  468                           * sadb_unlinkassoc() will decrement the refcnt.  Bump
 469  469                           * up when we have the lock so that we don't have to
 470  470                           * acquire locks when we come back from
 471  471                           * sadb_insertassoc().
 472  472                           *
 473  473                           * We don't need to bump the bucket's gen since
 474  474                           * we aren't moving to a new bucket.
 475  475                           */
 476  476                          IPSA_REFHOLD(retval);
 477  477                          IPSA_COPY_ADDR(retval->ipsa_srcaddr, src, af);
 478  478                          mutex_exit(&retval->ipsa_lock);
 479  479                          sadb_unlinkassoc(retval);
 480  480                          /*
 481  481                           * Since the bucket lock is held, we know
 482  482                           * sadb_insertassoc() will succeed.
 483  483                           */
 484  484  #ifdef DEBUG
 485  485                          if (sadb_insertassoc(retval, bucket) != 0) {
 486  486                                  cmn_err(CE_PANIC,
 487  487                                      "sadb_insertassoc() failed in "
 488  488                                      "ipsec_getassocbyconn().\n");
 489  489                          }
 490  490  #else   /* non-DEBUG */
 491  491                          (void) sadb_insertassoc(retval, bucket);
 492  492  #endif  /* DEBUG */
 493  493                          return (retval);
 494  494                  }
 495  495          }
 496  496          mutex_exit(&retval->ipsa_lock);
 497  497  
 498  498          return (retval);
 499  499  }
 500  500  
 501  501  /*
 502  502   * Look up a security association based on the security parameters index (SPI)
 503  503   * and address(es).  This is used for inbound packets and general SA lookups
 504  504   * (even in outbound SA tables).  The source address may be ignored.  Return
 505  505   * NULL if no association is available.  If an SA is found, return it, with
 506  506   * its refcnt incremented.  The caller must REFRELE after using the SA.
 507  507   * The hash bucket must be locked down before calling.
 508  508   */
 509  509  ipsa_t *
 510  510  ipsec_getassocbyspi(isaf_t *bucket, uint32_t spi, uint32_t *src, uint32_t *dst,
 511  511      sa_family_t af)
 512  512  {
 513  513          ipsa_t *retval;
 514  514  
 515  515          ASSERT(MUTEX_HELD(&bucket->isaf_lock));
 516  516  
 517  517          /*
 518  518           * Walk the hash bucket, matching exactly on SPI, then destination,
 519  519           * then source.
 520  520           *
 521  521           * Per-SA locking doesn't need to happen, because I'm only matching
 522  522           * on addresses.  Addresses are only changed during insertion/deletion
 523  523           * from the hash bucket.  Since the hash bucket lock is held, we don't
 524  524           * need to worry about addresses changing.
 525  525           */
 526  526  
 527  527          for (retval = bucket->isaf_ipsa; retval != NULL;
 528  528              retval = retval->ipsa_next) {
 529  529                  if (retval->ipsa_spi != spi)
 530  530                          continue;
 531  531                  if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af))
 532  532                          continue;
 533  533  
 534  534                  /*
 535  535                   * Assume that wildcard source addresses are inserted at the
 536  536                   * end of the hash bucket.  (See sadb_insertassoc().)
 537  537                   * The following check for source addresses is a weak form
 538  538                   * of access control/source identity verification.  If an
 539  539                   * SA has a source address, I only match an all-zeroes
 540  540                   * source address, or that particular one.  If the SA has
 541  541                   * an all-zeroes source, then I match regardless.
 542  542                   *
 543  543                   * There is a weakness here in that a packet with all-zeroes
 544  544                   * for an address will match regardless of the source address
 545  545                   * stored in the packet.
 546  546                   *
 547  547                   * Note that port-level packet selectors, if present,
 548  548                   * are checked in ipsec_check_ipsecin_unique().
 549  549                   */
 550  550                  if (IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) ||
 551  551                      IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af) ||
 552  552                      IPSA_IS_ADDR_UNSPEC(src, af))
 553  553                          break;
 554  554          }
 555  555  
 556  556          if (retval != NULL) {
 557  557                  /*
 558  558                   * Just refhold the return value.  The caller will then
 559  559                   * make the appropriate calls to set the USED flag.
 560  560                   */
 561  561                  IPSA_REFHOLD(retval);
 562  562          }
 563  563  
 564  564          return (retval);
 565  565  }
 566  566  
 567  567  boolean_t
 568  568  ipsec_outbound_sa(mblk_t *data_mp, ip_xmit_attr_t *ixa, uint_t proto)
 569  569  {
 570  570          ipaddr_t dst;
 571  571          uint32_t *dst_ptr, *src_ptr;
 572  572          isaf_t *bucket;
 573  573          ipsa_t *assoc;
 574  574          ip_pkt_t ipp;
 575  575          in6_addr_t dst6;
 576  576          ipsa_t **sa;
 577  577          sadbp_t *sadbp;
 578  578          sadb_t *sp;
 579  579          sa_family_t af;
 580  580          ip_stack_t      *ipst = ixa->ixa_ipst;
 581  581          netstack_t      *ns = ipst->ips_netstack;
 582  582  
 583  583          ASSERT(ixa->ixa_flags & IXAF_IPSEC_SECURE);
 584  584  
 585  585          if (proto == IPPROTO_ESP) {
 586  586                  ipsecesp_stack_t        *espstack;
 587  587  
 588  588                  espstack = ns->netstack_ipsecesp;
 589  589                  sa = &ixa->ixa_ipsec_esp_sa;
 590  590                  sadbp = &espstack->esp_sadb;
 591  591          } else {
 592  592                  ipsecah_stack_t *ahstack;
 593  593  
 594  594                  ASSERT(proto == IPPROTO_AH);
 595  595                  ahstack = ns->netstack_ipsecah;
 596  596                  sa = &ixa->ixa_ipsec_ah_sa;
 597  597                  sadbp = &ahstack->ah_sadb;
 598  598          }
 599  599  
 600  600          ASSERT(*sa == NULL);
 601  601  
 602  602          if (ixa->ixa_flags & IXAF_IS_IPV4) {
 603  603                  ipha_t *ipha = (ipha_t *)data_mp->b_rptr;
 604  604  
 605  605                  ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
 606  606                  dst = ip_get_dst(ipha);
 607  607                  sp = &sadbp->s_v4;
 608  608                  af = AF_INET;
 609  609  
 610  610                  /*
 611  611                   * NOTE:Getting the outbound association is considerably
 612  612                   *      painful.  ipsec_getassocbyconn() will require more
 613  613                   *      parameters as policy implementations mature.
 614  614                   */
 615  615                  bucket = OUTBOUND_BUCKET_V4(sp, dst);
 616  616                  src_ptr = (uint32_t *)&ipha->ipha_src;
 617  617                  dst_ptr = (uint32_t *)&dst;
 618  618          } else {
 619  619                  ip6_t *ip6h = (ip6_t *)data_mp->b_rptr;
 620  620  
 621  621                  ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
 622  622                  dst6 = ip_get_dst_v6(ip6h, data_mp, NULL);
 623  623                  af = AF_INET6;
 624  624  
 625  625                  bzero(&ipp, sizeof (ipp));
 626  626                  sp = &sadbp->s_v6;
 627  627  
 628  628                  /* Same NOTE: applies here! */
 629  629                  bucket = OUTBOUND_BUCKET_V6(sp, dst6);
 630  630                  src_ptr = (uint32_t *)&ip6h->ip6_src;
 631  631                  dst_ptr = (uint32_t *)&dst6;
 632  632          }
 633  633  
 634  634          mutex_enter(&bucket->isaf_lock);
 635  635          assoc = ipsec_getassocbyconn(bucket, ixa, src_ptr, dst_ptr, af,
 636  636              proto, ixa->ixa_tsl);
 637  637          mutex_exit(&bucket->isaf_lock);
 638  638  
 639  639          if (assoc == NULL)
 640  640                  return (B_FALSE);
 641  641  
 642  642          if (assoc->ipsa_state == IPSA_STATE_DEAD) {
 643  643                  IPSA_REFRELE(assoc);
 644  644                  return (B_FALSE);
 645  645          }
 646  646  
 647  647          ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL);
 648  648  
 649  649          *sa = assoc;
 650  650          return (B_TRUE);
 651  651  }
 652  652  
 653  653  /*
 654  654   * Inbound IPsec SA selection.
 655  655   * Can return a pulled up mblk.
 656  656   * When it returns non-NULL ahp is updated
 657  657   */
 658  658  mblk_t *
 659  659  ipsec_inbound_ah_sa(mblk_t *mp, ip_recv_attr_t *ira, ah_t **ahp)
 660  660  {
 661  661          ipha_t *ipha;
 662  662          ipsa_t  *assoc;
 663  663          ah_t *ah;
 664  664          isaf_t *hptr;
 665  665          boolean_t isv6;
 666  666          ip6_t *ip6h;
 667  667          int ah_offset;
 668  668          uint32_t *src_ptr, *dst_ptr;
 669  669          int pullup_len;
 670  670          sadb_t *sp;
 671  671          sa_family_t af;
 672  672          netstack_t      *ns = ira->ira_ill->ill_ipst->ips_netstack;
 673  673          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 674  674          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
 675  675  
 676  676          IP_AH_BUMP_STAT(ipss, in_requests);
 677  677  
 678  678          isv6 = !(ira->ira_flags & IRAF_IS_IPV4);
 679  679          if (isv6) {
 680  680                  ip6h = (ip6_t *)mp->b_rptr;
 681  681                  ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE);
 682  682          } else {
 683  683                  ipha = (ipha_t *)mp->b_rptr;
 684  684                  ASSERT(ipha->ipha_protocol == IPPROTO_AH);
 685  685                  ah_offset = ipha->ipha_version_and_hdr_length -
 686  686                      (uint8_t)((IP_VERSION << 4));
 687  687                  ah_offset <<= 2;
 688  688          }
 689  689  
 690  690          /*
 691  691           * We assume that the IP header is pulled up until
 692  692           * the options. We need to see whether we have the
 693  693           * AH header in the same mblk or not.
 694  694           */
 695  695          pullup_len = ah_offset + sizeof (ah_t);
 696  696          if (mp->b_rptr + pullup_len > mp->b_wptr) {
 697  697                  if (!pullupmsg(mp, pullup_len)) {
 698  698                          ipsec_rl_strlog(ns, ip_mod_info.mi_idnum, 0, 0,
 699  699                              SL_WARN | SL_ERROR,
 700  700                              "ipsec_inbound_ah_sa: Small AH header\n");
 701  701                          IP_AH_BUMP_STAT(ipss, in_discards);
 702  702                          ip_drop_packet(mp, B_TRUE, ira->ira_ill,
 703  703                              DROPPER(ipss, ipds_ah_bad_length),
 704  704                              &ipss->ipsec_dropper);
 705  705                          return (NULL);
 706  706                  }
 707  707                  if (isv6)
 708  708                          ip6h = (ip6_t *)mp->b_rptr;
 709  709                  else
 710  710                          ipha = (ipha_t *)mp->b_rptr;
 711  711          }
 712  712  
 713  713          ah = (ah_t *)(mp->b_rptr + ah_offset);
 714  714  
 715  715          if (isv6) {
 716  716                  src_ptr = (uint32_t *)&ip6h->ip6_src;
 717  717                  dst_ptr = (uint32_t *)&ip6h->ip6_dst;
 718  718                  sp = &ahstack->ah_sadb.s_v6;
 719  719                  af = AF_INET6;
 720  720          } else {
 721  721                  src_ptr = (uint32_t *)&ipha->ipha_src;
  
    | 
      ↓ open down ↓ | 
    721 lines elided | 
    
      ↑ open up ↑ | 
  
 722  722                  dst_ptr = (uint32_t *)&ipha->ipha_dst;
 723  723                  sp = &ahstack->ah_sadb.s_v4;
 724  724                  af = AF_INET;
 725  725          }
 726  726  
 727  727          hptr = INBOUND_BUCKET(sp, ah->ah_spi);
 728  728          mutex_enter(&hptr->isaf_lock);
 729  729          assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af);
 730  730          mutex_exit(&hptr->isaf_lock);
 731  731  
 732      -        if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD ||
 733      -            assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
      732 +        if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD) {
 734  733                  IP_AH_BUMP_STAT(ipss, lookup_failure);
 735  734                  IP_AH_BUMP_STAT(ipss, in_discards);
 736  735                  ipsecah_in_assocfailure(mp, 0,
 737  736                      SL_ERROR | SL_CONSOLE | SL_WARN,
 738  737                      "ipsec_inbound_ah_sa: No association found for "
 739  738                      "spi 0x%x, dst addr %s\n",
 740  739                      ah->ah_spi, dst_ptr, af, ira);
 741  740                  if (assoc != NULL) {
 742  741                          IPSA_REFRELE(assoc);
 743  742                  }
 744  743                  return (NULL);
 745  744          }
 746  745  
 747  746          if (assoc->ipsa_state == IPSA_STATE_LARVAL) {
 748  747                  /* Not fully baked; swap the packet under a rock until then */
 749  748  
 750  749                  mp = sadb_set_lpkt(assoc, mp, ira);
 751  750                  if (mp == NULL) {
 752  751                          IPSA_REFRELE(assoc);
 753  752                          return (NULL);
 754  753                  }
 755  754                  /* Looks like the SA is no longer LARVAL. */
 756  755          }
 757  756  
 758  757          /* Are the IPsec fields initialized at all? */
 759  758          if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
 760  759                  ira->ira_ipsec_action = NULL;
 761  760                  ira->ira_ipsec_ah_sa = NULL;
 762  761                  ira->ira_ipsec_esp_sa = NULL;
 763  762          }
 764  763  
 765  764          /*
 766  765           * Save a reference to the association so that it can
 767  766           * be retrieved after execution. We free any AH SA reference
 768  767           * already there (innermost SA "wins". The reference to
 769  768           * the SA will also be used later when doing the policy checks.
 770  769           */
 771  770          if (ira->ira_ipsec_ah_sa != NULL) {
 772  771                  IPSA_REFRELE(ira->ira_ipsec_ah_sa);
 773  772          }
 774  773          ira->ira_flags |= IRAF_IPSEC_SECURE;
 775  774          ira->ira_ipsec_ah_sa = assoc;
 776  775  
 777  776          *ahp = ah;
 778  777          return (mp);
 779  778  }
 780  779  
 781  780  /*
 782  781   * Can return a pulled up mblk.
 783  782   * When it returns non-NULL esphp is updated
 784  783   */
 785  784  mblk_t *
 786  785  ipsec_inbound_esp_sa(mblk_t *data_mp, ip_recv_attr_t *ira, esph_t **esphp)
 787  786  {
 788  787          mblk_t *placeholder;
 789  788          uint32_t *src_ptr, *dst_ptr;
 790  789          ipha_t *ipha;
 791  790          ip6_t *ip6h;
 792  791          esph_t *esph;
 793  792          ipsa_t *ipsa;
 794  793          isaf_t *bucket;
 795  794          uint_t preamble;
 796  795          sa_family_t af;
 797  796          boolean_t isv6;
 798  797          sadb_t *sp;
 799  798          netstack_t      *ns = ira->ira_ill->ill_ipst->ips_netstack;
 800  799          ipsec_stack_t   *ipss = ns->netstack_ipsec;
 801  800          ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
 802  801  
 803  802          IP_ESP_BUMP_STAT(ipss, in_requests);
 804  803  
 805  804          isv6 = !(ira->ira_flags & IRAF_IS_IPV4);
 806  805          if (isv6) {
 807  806                  ip6h = (ip6_t *)data_mp->b_rptr;
 808  807          } else {
 809  808                  ipha = (ipha_t *)data_mp->b_rptr;
 810  809          }
 811  810  
 812  811          /*
 813  812           * Put all data into one mblk if it's not there already.
 814  813           * XXX This is probably bad long-term.  Figure out better ways of doing
 815  814           * this.  Much of the inbound path depends on all of the data being
 816  815           * in one mblk.
 817  816           *
 818  817           * XXX Jumbogram issues will have to be dealt with here.
 819  818           * If the plen is 0, we'll have to scan for a HBH header with the
 820  819           * actual packet length.
 821  820           */
 822  821          if (data_mp->b_datap->db_ref > 1 ||
 823  822              (data_mp->b_wptr - data_mp->b_rptr) < ira->ira_pktlen) {
 824  823                  placeholder = msgpullup(data_mp, -1);
 825  824                  if (placeholder == NULL) {
 826  825                          IP_ESP_BUMP_STAT(ipss, in_discards);
 827  826                          ip_drop_packet(data_mp, B_TRUE, ira->ira_ill,
 828  827                              DROPPER(ipss, ipds_esp_nomem),
 829  828                              &ipss->ipsec_dropper);
 830  829                          return (NULL);
 831  830                  } else {
 832  831                          /* Reset packet with new pulled up mblk. */
 833  832                          freemsg(data_mp);
 834  833                          data_mp = placeholder;
 835  834                  }
 836  835          }
 837  836  
 838  837          /*
 839  838           * Find the ESP header, point the address pointers at the appropriate
 840  839           * IPv4/IPv6 places.
 841  840           */
 842  841          if (isv6) {
 843  842                  ip6h = (ip6_t *)data_mp->b_rptr;
 844  843                  src_ptr = (uint32_t *)&ip6h->ip6_src;
 845  844                  dst_ptr = (uint32_t *)&ip6h->ip6_dst;
 846  845                  if (ip6h->ip6_nxt != IPPROTO_ESP) {
 847  846                          /* There are options that need to be processed. */
 848  847                          preamble = ip_hdr_length_v6(data_mp, ip6h);
 849  848                  } else {
 850  849                          preamble = sizeof (ip6_t);
 851  850                  }
 852  851  
 853  852                  sp = &espstack->esp_sadb.s_v6;
 854  853                  af = AF_INET6;
 855  854          } else {
 856  855                  ipha = (ipha_t *)data_mp->b_rptr;
 857  856                  src_ptr = (uint32_t *)&ipha->ipha_src;
 858  857                  dst_ptr = (uint32_t *)&ipha->ipha_dst;
 859  858                  preamble = IPH_HDR_LENGTH(ipha);
 860  859  
 861  860                  sp = &espstack->esp_sadb.s_v4;
 862  861                  af = AF_INET;
 863  862          }
  
    | 
      ↓ open down ↓ | 
    120 lines elided | 
    
      ↑ open up ↑ | 
  
 864  863  
 865  864          esph = (esph_t *)(data_mp->b_rptr + preamble);
 866  865  
 867  866          /* Since hash is common on inbound (SPI value), hash here. */
 868  867          bucket = INBOUND_BUCKET(sp, esph->esph_spi);
 869  868          mutex_enter(&bucket->isaf_lock);
 870  869          ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr,
 871  870              af);
 872  871          mutex_exit(&bucket->isaf_lock);
 873  872  
 874      -        if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD ||
 875      -            ipsa->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
      873 +        if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD) {
 876  874                  /*  This is a loggable error!  AUDIT ME! */
 877  875                  IP_ESP_BUMP_STAT(ipss, lookup_failure);
 878  876                  IP_ESP_BUMP_STAT(ipss, in_discards);
 879  877                  ipsecesp_in_assocfailure(data_mp, 0,
 880  878                      SL_ERROR | SL_CONSOLE | SL_WARN,
 881  879                      "ipsec_inbound_esp_sa: No association found for "
 882  880                      "spi 0x%x, dst addr %s\n",
 883  881                      esph->esph_spi, dst_ptr, af, ira);
 884  882                  if (ipsa != NULL) {
 885  883                          IPSA_REFRELE(ipsa);
 886  884                  }
 887  885                  return (NULL);
 888  886          }
 889  887  
 890  888          if (ipsa->ipsa_state == IPSA_STATE_LARVAL) {
 891  889                  /* Not fully baked; swap the packet under a rock until then */
 892  890  
 893  891                  data_mp = sadb_set_lpkt(ipsa, data_mp, ira);
 894  892                  if (data_mp == NULL) {
 895  893                          IPSA_REFRELE(ipsa);
 896  894                          return (NULL);
 897  895                  }
 898  896                  /* Looks like the SA is no longer LARVAL. */
 899  897          }
 900  898  
 901  899          /* Are the IPsec fields initialized at all? */
 902  900          if (!(ira->ira_flags & IRAF_IPSEC_SECURE)) {
 903  901                  ira->ira_ipsec_action = NULL;
 904  902                  ira->ira_ipsec_ah_sa = NULL;
 905  903                  ira->ira_ipsec_esp_sa = NULL;
 906  904          }
 907  905  
 908  906          /*
 909  907           * Save a reference to the association so that it can
 910  908           * be retrieved after execution. We free any AH SA reference
 911  909           * already there (innermost SA "wins". The reference to
 912  910           * the SA will also be used later when doing the policy checks.
 913  911           */
 914  912          if (ira->ira_ipsec_esp_sa != NULL) {
 915  913                  IPSA_REFRELE(ira->ira_ipsec_esp_sa);
 916  914          }
 917  915          ira->ira_flags |= IRAF_IPSEC_SECURE;
 918  916          ira->ira_ipsec_esp_sa = ipsa;
 919  917  
 920  918          *esphp = esph;
 921  919          return (data_mp);
 922  920  }
  
    | 
      ↓ open down ↓ | 
    37 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX