The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/pfkeyv2_parsemessage.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: pfkeyv2_parsemessage.c,v 1.60 2021/07/14 22:39:26 tobhe Exp $ */
    2 
    3 /*
    4  *      @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
    5  *
    6  * NRL grants permission for redistribution and use in source and binary
    7  * forms, with or without modification, of the software and documentation
    8  * created at NRL provided that the following conditions are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgements:
   17  *      This product includes software developed by the University of
   18  *      California, Berkeley and its contributors.
   19  *      This product includes software developed at the Information
   20  *      Technology Division, US Naval Research Laboratory.
   21  * 4. Neither the name of the NRL nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
   26  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   28  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
   29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   36  *
   37  * The views and conclusions contained in the software and documentation
   38  * are those of the authors and should not be interpreted as representing
   39  * official policies, either expressed or implied, of the US Naval
   40  * Research Laboratory (NRL).
   41  */
   42 
   43 /*
   44  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. Redistributions in binary form must reproduce the above copyright
   52  *    notice, this list of conditions and the following disclaimer in the
   53  *    documentation and/or other materials provided with the distribution.
   54  * 3. Neither the name of the author nor the names of any contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   68  * SUCH DAMAGE.
   69  */
   70 
   71 #include "pf.h"
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/socket.h>
   76 #include <sys/mbuf.h>
   77 #include <sys/proc.h>
   78 #include <netinet/ip_ipsp.h>
   79 #include <net/pfkeyv2.h>
   80 
   81 #if NPF > 0
   82 #include <net/if.h>
   83 #include <net/pfvar.h>
   84 #endif
   85 
   86 #ifdef ENCDEBUG
   87 #define DPRINTF(fmt, args...)                                           \
   88         do {                                                            \
   89                 if (encdebug)                                           \
   90                         printf("%s: " fmt "\n", __func__, ## args);     \
   91         } while (0)
   92 #else
   93 #define DPRINTF(fmt, args...)                                           \
   94         do { } while (0)
   95 #endif
   96 
   97 #define BITMAP_SA                      (1LL << SADB_EXT_SA)
   98 #define BITMAP_LIFETIME_CURRENT        (1LL << SADB_EXT_LIFETIME_CURRENT)
   99 #define BITMAP_LIFETIME_HARD           (1LL << SADB_EXT_LIFETIME_HARD)
  100 #define BITMAP_LIFETIME_SOFT           (1LL << SADB_EXT_LIFETIME_SOFT)
  101 #define BITMAP_ADDRESS_SRC             (1LL << SADB_EXT_ADDRESS_SRC)
  102 #define BITMAP_ADDRESS_DST             (1LL << SADB_EXT_ADDRESS_DST)
  103 #define BITMAP_ADDRESS_PROXY           (1LL << SADB_EXT_ADDRESS_PROXY)
  104 #define BITMAP_KEY_AUTH                (1LL << SADB_EXT_KEY_AUTH)
  105 #define BITMAP_KEY_ENCRYPT             (1LL << SADB_EXT_KEY_ENCRYPT)
  106 #define BITMAP_IDENTITY_SRC            (1LL << SADB_EXT_IDENTITY_SRC)
  107 #define BITMAP_IDENTITY_DST            (1LL << SADB_EXT_IDENTITY_DST)
  108 #define BITMAP_SENSITIVITY             (1LL << SADB_EXT_SENSITIVITY)
  109 #define BITMAP_PROPOSAL                (1LL << SADB_EXT_PROPOSAL)
  110 #define BITMAP_SUPPORTED_AUTH          (1LL << SADB_EXT_SUPPORTED_AUTH)
  111 #define BITMAP_SUPPORTED_ENCRYPT       (1LL << SADB_EXT_SUPPORTED_ENCRYPT)
  112 #define BITMAP_SPIRANGE                (1LL << SADB_EXT_SPIRANGE)
  113 #define BITMAP_LIFETIME (BITMAP_LIFETIME_CURRENT | BITMAP_LIFETIME_HARD | BITMAP_LIFETIME_SOFT)
  114 #define BITMAP_ADDRESS (BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST)
  115 #define BITMAP_KEY      (BITMAP_KEY_AUTH | BITMAP_KEY_ENCRYPT)
  116 #define BITMAP_IDENTITY (BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST)
  117 #define BITMAP_MSG                     1
  118 #define BITMAP_X_SRC_MASK              (1LL << SADB_X_EXT_SRC_MASK)
  119 #define BITMAP_X_DST_MASK              (1LL << SADB_X_EXT_DST_MASK)
  120 #define BITMAP_X_PROTOCOL              (1LL << SADB_X_EXT_PROTOCOL)
  121 #define BITMAP_X_SRC_FLOW              (1LL << SADB_X_EXT_SRC_FLOW)
  122 #define BITMAP_X_DST_FLOW              (1LL << SADB_X_EXT_DST_FLOW)
  123 #define BITMAP_X_FLOW_TYPE             (1LL << SADB_X_EXT_FLOW_TYPE)
  124 #define BITMAP_X_SA2                   (1LL << SADB_X_EXT_SA2)
  125 #define BITMAP_X_DST2                  (1LL << SADB_X_EXT_DST2)
  126 #define BITMAP_X_POLICY                (1LL << SADB_X_EXT_POLICY)
  127 #define BITMAP_X_FLOW                  (BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE)
  128 #define BITMAP_X_SUPPORTED_COMP        (1LL << SADB_X_EXT_SUPPORTED_COMP)
  129 #define BITMAP_X_UDPENCAP              (1LL << SADB_X_EXT_UDPENCAP)
  130 #define BITMAP_X_LIFETIME_LASTUSE      (1LL << SADB_X_EXT_LIFETIME_LASTUSE)
  131 #define BITMAP_X_TAG                   (1LL << SADB_X_EXT_TAG)
  132 #define BITMAP_X_TAP                   (1LL << SADB_X_EXT_TAP)
  133 #define BITMAP_X_SATYPE2               (1LL << SADB_X_EXT_SATYPE2)
  134 #define BITMAP_X_RDOMAIN               (1LL << SADB_X_EXT_RDOMAIN)
  135 #define BITMAP_X_COUNTER               (1LL << SADB_X_EXT_COUNTER)
  136 #define BITMAP_X_MTU                   (1LL << SADB_X_EXT_MTU)
  137 #define BITMAP_X_REPLAY                (1LL << SADB_X_EXT_REPLAY)
  138 
  139 uint64_t sadb_exts_allowed_in[SADB_MAX+1] =
  140 {
  141         /* RESERVED */
  142         ~0,
  143         /* GETSPI */
  144         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
  145         /* UPDATE */
  146         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN,
  147         /* ADD */
  148         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN,
  149         /* DELETE */
  150         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN,
  151         /* GET */
  152         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN,
  153         /* ACQUIRE */
  154         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
  155         /* REGISTER */
  156         0,
  157         /* EXPIRE */
  158         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
  159         /* FLUSH */
  160         0,
  161         /* DUMP */
  162         0,
  163         /* X_PROMISC */
  164         0,
  165         /* X_ADDFLOW */
  166         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW | BITMAP_X_RDOMAIN,
  167         /* X_DELFLOW */
  168         BITMAP_X_FLOW | BITMAP_X_RDOMAIN,
  169         /* X_GRPSPIS */
  170         BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN,
  171         /* X_ASKPOLICY */
  172         BITMAP_X_POLICY,
  173 };
  174 
  175 uint64_t sadb_exts_required_in[SADB_MAX+1] =
  176 {
  177         /* RESERVED */
  178         0,
  179         /* GETSPI */
  180         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
  181         /* UPDATE */
  182         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
  183         /* ADD */
  184         BITMAP_SA | BITMAP_ADDRESS_DST,
  185         /* DELETE */
  186         BITMAP_SA | BITMAP_ADDRESS_DST,
  187         /* GET */
  188         BITMAP_SA | BITMAP_ADDRESS_DST,
  189         /* ACQUIRE */
  190         0,
  191         /* REGISTER */
  192         0,
  193         /* EXPIRE */
  194         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
  195         /* FLUSH */
  196         0,
  197         /* DUMP */
  198         0,
  199         /* X_PROMISC */
  200         0,
  201         /* X_ADDFLOW */
  202         BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
  203         /* X_DELFLOW */
  204         BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
  205         /* X_GRPSPIS */
  206         BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2,
  207         /* X_ASKPOLICY */
  208         BITMAP_X_POLICY,
  209 };
  210 
  211 const uint64_t sadb_exts_allowed_out[SADB_MAX+1] =
  212 {
  213         /* RESERVED */
  214         ~0,
  215         /* GETSPI */
  216         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
  217         /* UPDATE */
  218         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN,
  219         /* ADD */
  220         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN,
  221         /* DELETE */
  222         BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN,
  223         /* GET */
  224         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN | BITMAP_X_MTU | BITMAP_X_REPLAY,
  225         /* ACQUIRE */
  226         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
  227         /* REGISTER */
  228         BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP,
  229         /* EXPIRE */
  230         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS,
  231         /* FLUSH */
  232         0,
  233         /* DUMP */
  234         BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY,
  235         /* X_PROMISC */
  236         0,
  237         /* X_ADDFLOW */
  238         BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_RDOMAIN,
  239         /* X_DELFLOW */
  240         BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_X_RDOMAIN,
  241         /* X_GRPSPIS */
  242         BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN,
  243         /* X_ASKPOLICY */
  244         BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY,
  245 };
  246 
  247 const uint64_t sadb_exts_required_out[SADB_MAX+1] =
  248 {
  249         /* RESERVED */
  250         0,
  251         /* GETSPI */
  252         BITMAP_SA | BITMAP_ADDRESS_DST,
  253         /* UPDATE */
  254         BITMAP_SA | BITMAP_ADDRESS_DST,
  255         /* ADD */
  256         BITMAP_SA | BITMAP_ADDRESS_DST,
  257         /* DELETE */
  258         BITMAP_SA | BITMAP_ADDRESS_DST,
  259         /* GET */
  260         BITMAP_SA | BITMAP_LIFETIME_CURRENT | BITMAP_ADDRESS_DST,
  261         /* ACQUIRE */
  262         0,
  263         /* REGISTER */
  264         BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP,
  265         /* EXPIRE */
  266         BITMAP_SA | BITMAP_ADDRESS_DST,
  267         /* FLUSH */
  268         0,
  269         /* DUMP */
  270         0,
  271         /* X_PROMISC */
  272         0,
  273         /* X_ADDFLOW */
  274         BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
  275         /* X_DELFLOW */
  276         BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
  277         /* X_GRPSPIS */
  278         BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2,
  279         /* X_REPPOLICY */
  280         BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE,
  281 };
  282 
  283 int
  284 pfkeyv2_parsemessage(void *p, int len, void **headers)
  285 {
  286         struct sadb_ext *sadb_ext;
  287         int i, left = len;
  288         uint64_t allow, seen = 1;
  289         struct sadb_msg *sadb_msg = (struct sadb_msg *) p;
  290 
  291         bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *));
  292 
  293         if (left < sizeof(struct sadb_msg)) {
  294                 DPRINTF("message too short");
  295                 return (EINVAL);
  296         }
  297 
  298         headers[0] = p;
  299 
  300         if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) {
  301                 DPRINTF("length not a multiple of 64");
  302                 return (EINVAL);
  303         }
  304 
  305         p += sizeof(struct sadb_msg);
  306         left -= sizeof(struct sadb_msg);
  307 
  308         if (sadb_msg->sadb_msg_reserved) {
  309                 DPRINTF("message header reserved field set");
  310                 return (EINVAL);
  311         }
  312 
  313         if (sadb_msg->sadb_msg_type > SADB_MAX) {
  314                 DPRINTF("message type > %d", SADB_MAX);
  315                 return (EINVAL);
  316         }
  317 
  318         if (!sadb_msg->sadb_msg_type) {
  319                 DPRINTF("message type unset");
  320                 return (EINVAL);
  321         }
  322 
  323         if (sadb_msg->sadb_msg_pid != curproc->p_p->ps_pid) {
  324                 DPRINTF("bad PID value");
  325                 return (EINVAL);
  326         }
  327 
  328         if (sadb_msg->sadb_msg_errno) {
  329                 if (left) {
  330                         DPRINTF("too-large error message");
  331                         return (EINVAL);
  332                 }
  333                 return (0);
  334         }
  335 
  336         if (sadb_msg->sadb_msg_type == SADB_X_PROMISC) {
  337                 DPRINTF("message type promiscuous");
  338                 return (0);
  339         }
  340 
  341         allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type];
  342 
  343         while (left > 0) {
  344                 sadb_ext = (struct sadb_ext *)p;
  345                 if (left < sizeof(struct sadb_ext)) {
  346                         DPRINTF("extension header too short");
  347                         return (EINVAL);
  348                 }
  349 
  350                 i = sadb_ext->sadb_ext_len * sizeof(uint64_t);
  351                 if (left < i) {
  352                         DPRINTF("extension header exceeds message length");
  353                         return (EINVAL);
  354                 }
  355 
  356                 if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) {
  357                         DPRINTF("unknown extension header %d",
  358                             sadb_ext->sadb_ext_type);
  359                         return (EINVAL);
  360                 }
  361 
  362                 if (!sadb_ext->sadb_ext_type) {
  363                         DPRINTF("unset extension header");
  364                         return (EINVAL);
  365                 }
  366 
  367                 if (!(allow & (1LL << sadb_ext->sadb_ext_type))) {
  368                         DPRINTF("extension header %d not permitted on message "
  369                             "type %d",
  370                             sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type);
  371                         return (EINVAL);
  372                 }
  373 
  374                 if (headers[sadb_ext->sadb_ext_type]) {
  375                         DPRINTF("duplicate extension header %d",
  376                             sadb_ext->sadb_ext_type);
  377                         return (EINVAL);
  378                 }
  379 
  380                 seen |= (1LL << sadb_ext->sadb_ext_type);
  381 
  382                 switch (sadb_ext->sadb_ext_type) {
  383                 case SADB_EXT_SA:
  384                 case SADB_X_EXT_SA2:
  385                 {
  386                         struct sadb_sa *sadb_sa = (struct sadb_sa *)p;
  387 
  388                         if (i != sizeof(struct sadb_sa)) {
  389                                 DPRINTF("bad header length for SA extension "
  390                                     "header %d",
  391                                     sadb_ext->sadb_ext_type);
  392                                 return (EINVAL);
  393                         }
  394 
  395                         if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) {
  396                                 DPRINTF("unknown SA state %d in SA extension "
  397                                     "header %d",
  398                                     sadb_sa->sadb_sa_state,
  399                                     sadb_ext->sadb_ext_type);
  400                                 return (EINVAL);
  401                         }
  402 
  403                         if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
  404                                 DPRINTF("cannot set SA state to dead, "
  405                                     "SA extension header %d",
  406                                     sadb_ext->sadb_ext_type);
  407                                 return (EINVAL);
  408                         }
  409 
  410                         if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
  411                                 DPRINTF("unknown encryption algorithm %d "
  412                                     "in SA extension header %d",
  413                                     sadb_sa->sadb_sa_encrypt,
  414                                     sadb_ext->sadb_ext_type);
  415                                 return (EINVAL);
  416                         }
  417 
  418                         if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) {
  419                                 DPRINTF("unknown authentication algorithm %d "
  420                                     "in SA extension header %d",
  421                                     sadb_sa->sadb_sa_auth,
  422                                     sadb_ext->sadb_ext_type);
  423                                 return (EINVAL);
  424                         }
  425 
  426                         if (sadb_sa->sadb_sa_replay > 64) {
  427                                 DPRINTF("unsupported replay window size %d "
  428                                     "in SA extension header %d",
  429                                     sadb_sa->sadb_sa_replay,
  430                                     sadb_ext->sadb_ext_type);
  431                                 return (EINVAL);
  432                         }
  433                 }
  434                 break;
  435                 case SADB_X_EXT_PROTOCOL:
  436                 case SADB_X_EXT_FLOW_TYPE:
  437                 case SADB_X_EXT_SATYPE2:
  438                         if (i != sizeof(struct sadb_protocol)) {
  439                                 DPRINTF("bad PROTOCOL/FLOW/SATYPE2 header "
  440                                     "length in extension header %d",
  441                                     sadb_ext->sadb_ext_type);
  442                                 return (EINVAL);
  443                         }
  444                         break;
  445                 case SADB_X_EXT_POLICY:
  446                         if (i != sizeof(struct sadb_x_policy)) {
  447                                 DPRINTF("bad POLICY header length");
  448                                 return (EINVAL);
  449                         }
  450                         break;
  451                 case SADB_EXT_LIFETIME_CURRENT:
  452                 case SADB_EXT_LIFETIME_HARD:
  453                 case SADB_EXT_LIFETIME_SOFT:
  454                 case SADB_X_EXT_LIFETIME_LASTUSE:
  455                         if (i != sizeof(struct sadb_lifetime)) {
  456                                 DPRINTF("bad header length for LIFETIME "
  457                                     "extension header %d",
  458                                     sadb_ext->sadb_ext_type);
  459                                 return (EINVAL);
  460                         }
  461                         break;
  462                 case SADB_EXT_ADDRESS_SRC:
  463                 case SADB_EXT_ADDRESS_DST:
  464                 case SADB_EXT_ADDRESS_PROXY:
  465                 case SADB_X_EXT_SRC_MASK:
  466                 case SADB_X_EXT_DST_MASK:
  467                 case SADB_X_EXT_SRC_FLOW:
  468                 case SADB_X_EXT_DST_FLOW:
  469                 case SADB_X_EXT_DST2:
  470                 {
  471                         struct sadb_address *sadb_address =
  472                             (struct sadb_address *)p;
  473                         struct sockaddr *sa = (struct sockaddr *)(p +
  474                             sizeof(struct sadb_address));
  475 
  476                         if (i < sizeof(struct sadb_address) +
  477                             sizeof(struct sockaddr)) {
  478                                 DPRINTF("bad ADDRESS extension header %d "
  479                                     "length",
  480                                     sadb_ext->sadb_ext_type);
  481                                 return (EINVAL);
  482                         }
  483 
  484                         if (sadb_address->sadb_address_reserved) {
  485                                 DPRINTF("ADDRESS extension header %d reserved "
  486                                     "field set",
  487                                     sadb_ext->sadb_ext_type);
  488                                 return (EINVAL);
  489                         }
  490                         if (sa->sa_len &&
  491                             (i != sizeof(struct sadb_address) +
  492                             PADUP(sa->sa_len))) {
  493                                 DPRINTF("bad sockaddr length field in ADDRESS "
  494                                     "extension header %d",
  495                                     sadb_ext->sadb_ext_type);
  496                                 return (EINVAL);
  497                         }
  498 
  499                         switch (sa->sa_family) {
  500                         case AF_INET:
  501                                 if (sizeof(struct sadb_address) +
  502                                     PADUP(sizeof(struct sockaddr_in)) != i) {
  503                                         DPRINTF("invalid ADDRESS extension "
  504                                             "header %d length",
  505                                             sadb_ext->sadb_ext_type);
  506                                         return (EINVAL);
  507                                 }
  508 
  509                                 if (sa->sa_len != sizeof(struct sockaddr_in)) {
  510                                         DPRINTF("bad sockaddr_in length in "
  511                                             "ADDRESS extension header %d",
  512                                             sadb_ext->sadb_ext_type);
  513                                         return (EINVAL);
  514                                 }
  515 
  516                                 /* Only check the right pieces */
  517                                 switch (sadb_ext->sadb_ext_type)
  518                                 {
  519                                 case SADB_X_EXT_SRC_MASK:
  520                                 case SADB_X_EXT_DST_MASK:
  521                                 case SADB_X_EXT_SRC_FLOW:
  522                                 case SADB_X_EXT_DST_FLOW:
  523                                         break;
  524 
  525                                 default:
  526                                         if (((struct sockaddr_in *)sa)->sin_port) {
  527                                                 DPRINTF("port field set in "
  528                                                     "sockaddr_in of ADDRESS "
  529                                                     "extension header %d",
  530                                                     sadb_ext->sadb_ext_type);
  531                                                 return (EINVAL);
  532                                         }
  533                                         break;
  534                                 }
  535 
  536                                 {
  537                                         char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)];
  538                                         bzero(zero, sizeof(zero));
  539 
  540                                         if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) {
  541                                                 DPRINTF("reserved sockaddr_in "
  542                                                     "field non-zero'ed in "
  543                                                     "ADDRESS extension header "
  544                                                     "%d",
  545                                                     sadb_ext->sadb_ext_type);
  546                                                 return (EINVAL);
  547                                         }
  548                                 }
  549                                 break;
  550 #ifdef INET6
  551                         case AF_INET6:
  552                                 if (i != sizeof(struct sadb_address) +
  553                                     PADUP(sizeof(struct sockaddr_in6))) {
  554                                         DPRINTF("invalid sockaddr_in6 length "
  555                                             "in ADDRESS extension header %d",
  556                                             sadb_ext->sadb_ext_type);
  557                                         return (EINVAL);
  558                                 }
  559 
  560                                 if (sa->sa_len !=
  561                                     sizeof(struct sockaddr_in6)) {
  562                                         DPRINTF("bad sockaddr_in6 length in "
  563                                             "ADDRESS extension header %d",
  564                                             sadb_ext->sadb_ext_type);
  565                                         return (EINVAL);
  566                                 }
  567 
  568                                 if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) {
  569                                         DPRINTF("flowinfo field set in "
  570                                             "sockaddr_in6 of ADDRESS "
  571                                             "extension header %d",
  572                                             sadb_ext->sadb_ext_type);
  573                                         return (EINVAL);
  574                                 }
  575 
  576                                 /* Only check the right pieces */
  577                                 switch (sadb_ext->sadb_ext_type)
  578                                 {
  579                                 case SADB_X_EXT_SRC_MASK:
  580                                 case SADB_X_EXT_DST_MASK:
  581                                 case SADB_X_EXT_SRC_FLOW:
  582                                 case SADB_X_EXT_DST_FLOW:
  583                                         break;
  584 
  585                                 default:
  586                                         if (((struct sockaddr_in6 *)sa)->sin6_port) {
  587                                                 DPRINTF("port field set in "
  588                                                     "sockaddr_in6 of ADDRESS "
  589                                                     "extension header %d",
  590                                                     sadb_ext->sadb_ext_type);
  591                                                 return (EINVAL);
  592                                         }
  593                                         break;
  594                                 }
  595                                 break;
  596 #endif /* INET6 */
  597                         default:
  598                                 if (sadb_msg->sadb_msg_satype ==
  599                                     SADB_X_SATYPE_TCPSIGNATURE &&
  600                                     sa->sa_family == 0)
  601                                         break;
  602                                 DPRINTF("unknown address family %d in ADDRESS "
  603                                     "extension header %d",
  604                                     sa->sa_family, sadb_ext->sadb_ext_type);
  605                                 return (EINVAL);
  606                         }
  607                 }
  608                 break;
  609                 case SADB_EXT_KEY_AUTH:
  610                 case SADB_EXT_KEY_ENCRYPT:
  611                 {
  612                         struct sadb_key *sadb_key = (struct sadb_key *)p;
  613 
  614                         if (i < sizeof(struct sadb_key)) {
  615                                 DPRINTF("bad header length in KEY extension "
  616                                     "header %d",
  617                                     sadb_ext->sadb_ext_type);
  618                                 return (EINVAL);
  619                         }
  620 
  621                         if (!sadb_key->sadb_key_bits) {
  622                                 DPRINTF("key length unset in KEY extension "
  623                                     "header %d",
  624                                     sadb_ext->sadb_ext_type);
  625                                 return (EINVAL);
  626                         }
  627 
  628                         if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) {
  629                                 DPRINTF("invalid key length in KEY extension "
  630                                     "header %d",
  631                                     sadb_ext->sadb_ext_type);
  632                                 return (EINVAL);
  633                         }
  634 
  635                         if (sadb_key->sadb_key_reserved) {
  636                                 DPRINTF("reserved field set in KEY extension "
  637                                     "header %d",
  638                                     sadb_ext->sadb_ext_type);
  639                                 return (EINVAL);
  640                         }
  641                 }
  642                 break;
  643                 case SADB_EXT_IDENTITY_SRC:
  644                 case SADB_EXT_IDENTITY_DST:
  645                 {
  646                         struct sadb_ident *sadb_ident = (struct sadb_ident *)p;
  647 
  648                         if (i < sizeof(struct sadb_ident)) {
  649                                 DPRINTF("bad header length of IDENTITY "
  650                                     "extension header %d",
  651                                     sadb_ext->sadb_ext_type);
  652                                 return (EINVAL);
  653                         }
  654 
  655                         if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
  656                                 DPRINTF("unknown identity type %d in IDENTITY "
  657                                     "extension header %d",
  658                                     sadb_ident->sadb_ident_type,
  659                                     sadb_ext->sadb_ext_type);
  660                                 return (EINVAL);
  661                         }
  662 
  663                         if (sadb_ident->sadb_ident_reserved) {
  664                                 DPRINTF("reserved field set in IDENTITY "
  665                                     "extension header %d",
  666                                     sadb_ext->sadb_ext_type);
  667                                 return (EINVAL);
  668                         }
  669 
  670                         if (i > sizeof(struct sadb_ident)) {
  671                                 char *c =
  672                                     (char *)(p + sizeof(struct sadb_ident));
  673                                 int j;
  674 
  675                                 if (*(char *)(p + i - 1)) {
  676                                         DPRINTF("non NUL-terminated identity "
  677                                             "in IDENTITY extension header %d",
  678                                             sadb_ext->sadb_ext_type);
  679                                         return (EINVAL);
  680                                 }
  681 
  682                                 j = PADUP(strlen(c) + 1) +
  683                                     sizeof(struct sadb_ident);
  684 
  685                                 if (i != j) {
  686                                         DPRINTF("actual identity length does "
  687                                             "not match expected length in "
  688                                             "identity extension header %d",
  689                                             sadb_ext->sadb_ext_type);
  690                                         return (EINVAL);
  691                                 }
  692                         }
  693                 }
  694                 break;
  695                 case SADB_EXT_SENSITIVITY:
  696                 {
  697                         struct sadb_sens *sadb_sens = (struct sadb_sens *)p;
  698 
  699                         if (i < sizeof(struct sadb_sens)) {
  700                                 DPRINTF("bad header length for SENSITIVITY "
  701                                     "extension header");
  702                                 return (EINVAL);
  703                         }
  704 
  705                         if (i != (sadb_sens->sadb_sens_sens_len +
  706                             sadb_sens->sadb_sens_integ_len) *
  707                             sizeof(uint64_t) +
  708                             sizeof(struct sadb_sens)) {
  709                                 DPRINTF("bad payload length for SENSITIVITY "
  710                                     "extension header");
  711                                 return (EINVAL);
  712                         }
  713                 }
  714                 break;
  715                 case SADB_EXT_PROPOSAL:
  716                 {
  717                         struct sadb_prop *sadb_prop = (struct sadb_prop *)p;
  718 
  719                         if (i < sizeof(struct sadb_prop)) {
  720                                 DPRINTF("bad PROPOSAL header length");
  721                                 return (EINVAL);
  722                         }
  723 
  724                         if (sadb_prop->sadb_prop_reserved) {
  725                                 DPRINTF("reserved fieldset in PROPOSAL "
  726                                     "extension header");
  727                                 return (EINVAL);
  728                         }
  729 
  730                         if ((i - sizeof(struct sadb_prop)) %
  731                             sizeof(struct sadb_comb)) {
  732                                 DPRINTF("bad proposal length");
  733                                 return (EINVAL);
  734                         }
  735 
  736                         {
  737                                 struct sadb_comb *sadb_comb =
  738                                     (struct sadb_comb *)(p +
  739                                         sizeof(struct sadb_prop));
  740                                 int j;
  741 
  742                                 for (j = 0;
  743                                     j < (i - sizeof(struct sadb_prop))/
  744                                     sizeof(struct sadb_comb);
  745                                     j++) {
  746                                         if (sadb_comb->sadb_comb_auth >
  747                                             SADB_AALG_MAX) {
  748                                                 DPRINTF("unknown "
  749                                                     "authentication algorithm "
  750                                                     "%d in PROPOSAL",
  751                                                     sadb_comb->sadb_comb_auth);
  752                                                 return (EINVAL);
  753                                         }
  754 
  755                                         if (sadb_comb->sadb_comb_encrypt >
  756                                             SADB_EALG_MAX) {
  757                                                 DPRINTF("unknown encryption "
  758                                                     "algorithm %d in PROPOSAL",
  759                                                     sadb_comb->
  760                                                     sadb_comb_encrypt);
  761                                                 return (EINVAL);
  762                                         }
  763 
  764                                         if (sadb_comb->sadb_comb_reserved) {
  765                                                 DPRINTF("reserved field set "
  766                                                     "in COMB header");
  767                                                 return (EINVAL);
  768                                         }
  769                                 }
  770                         }
  771                 }
  772                 break;
  773                 case SADB_EXT_SUPPORTED_AUTH:
  774                 case SADB_EXT_SUPPORTED_ENCRYPT:
  775                 case SADB_X_EXT_SUPPORTED_COMP:
  776                 {
  777                         struct sadb_supported *sadb_supported =
  778                             (struct sadb_supported *)p;
  779                         int j;
  780 
  781                         if (i < sizeof(struct sadb_supported)) {
  782                                 DPRINTF("bad header length for SUPPORTED "                                          "extension header %d",
  783                                     sadb_ext->sadb_ext_type);
  784                                 return (EINVAL);
  785                         }
  786 
  787                         if (sadb_supported->sadb_supported_reserved) {
  788                                 DPRINTF("reserved field set in SUPPORTED "
  789                                     "extension header %d",
  790                                     sadb_ext->sadb_ext_type);
  791                                 return (EINVAL);
  792                         }
  793 
  794                         {
  795                                 struct sadb_alg *sadb_alg =
  796                                     (struct sadb_alg *)(p +
  797                                         sizeof(struct sadb_supported));
  798                                 int max_alg;
  799 
  800                                 max_alg = sadb_ext->sadb_ext_type ==
  801                                     SADB_EXT_SUPPORTED_AUTH ?
  802                                     SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ?
  803                                     SADB_EALG_MAX : SADB_X_CALG_MAX;
  804 
  805                                 for (j = 0;
  806                                     j < sadb_supported->sadb_supported_len - 1;
  807                                     j++) {
  808                                         if (sadb_alg->sadb_alg_id > max_alg) {
  809                                                 DPRINTF("unknown algorithm %d "
  810                                                     "in SUPPORTED extension "
  811                                                     "header %d",
  812                                                     sadb_alg->sadb_alg_id,
  813                                                     sadb_ext->sadb_ext_type);
  814                                                 return (EINVAL);
  815                                         }
  816 
  817                                         if (sadb_alg->sadb_alg_reserved) {
  818                                                 DPRINTF("reserved field set "
  819                                                     "in supported algorithms "
  820                                                     "header inside SUPPORTED "
  821                                                     "extension header %d",
  822                                                     sadb_ext->sadb_ext_type);
  823                                                 return (EINVAL);
  824                                         }
  825 
  826                                         sadb_alg++;
  827                                 }
  828                         }
  829                 }
  830                 break;
  831                 case SADB_EXT_SPIRANGE:
  832                 {
  833                         struct sadb_spirange *sadb_spirange =
  834                             (struct sadb_spirange *)p;
  835 
  836                         if (i != sizeof(struct sadb_spirange)) {
  837                                 DPRINTF("bad header length of SPIRANGE "
  838                                     "extension header");
  839                                 return (EINVAL);
  840                         }
  841 
  842                         if (sadb_spirange->sadb_spirange_min >
  843                             sadb_spirange->sadb_spirange_max) {
  844                                 DPRINTF("bad SPI range");
  845                                 return (EINVAL);
  846                         }
  847                 }
  848                 break;
  849                 case SADB_X_EXT_UDPENCAP:
  850                         if (i != sizeof(struct sadb_x_udpencap)) {
  851                                 DPRINTF("bad UDPENCAP header length");
  852                                 return (EINVAL);
  853                         }
  854                         break;
  855                 case SADB_X_EXT_RDOMAIN:
  856                         if (i != sizeof(struct sadb_x_rdomain)) {
  857                                 DPRINTF("bad RDOMAIN header length");
  858                                 return (EINVAL);
  859                         }
  860                         break;
  861 #if NPF > 0
  862                 case SADB_X_EXT_TAG:
  863                         if (i < sizeof(struct sadb_x_tag)) {
  864                                 DPRINTF("TAG extension header too small");
  865                                 return (EINVAL);
  866                         }
  867                         if (i > (sizeof(struct sadb_x_tag) +
  868                             PF_TAG_NAME_SIZE)) {
  869                                 DPRINTF("TAG extension header too long");
  870                                 return (EINVAL);
  871                         }
  872                         break;
  873                 case SADB_X_EXT_TAP:
  874                         if (i < sizeof(struct sadb_x_tap)) {
  875                                 DPRINTF("TAP extension header too small");
  876                                 return (EINVAL);
  877                         }
  878                         if (i > sizeof(struct sadb_x_tap)) {
  879                                 DPRINTF("TAP extension header too long");
  880                                 return (EINVAL);
  881                         }
  882                         break;
  883 #endif
  884                 default:
  885                         DPRINTF("unknown extension header type %d",
  886                             sadb_ext->sadb_ext_type);
  887                         return (EINVAL);
  888                 }
  889 
  890                 headers[sadb_ext->sadb_ext_type] = p;
  891                 p += i;
  892                 left -= i;
  893         }
  894 
  895         if (left) {
  896                 DPRINTF("message too long");
  897                 return (EINVAL);
  898         }
  899 
  900         {
  901                 uint64_t required;
  902 
  903                 required = sadb_exts_required_in[sadb_msg->sadb_msg_type];
  904 
  905                 if ((seen & required) != required) {
  906                         DPRINTF("required fields missing");
  907                         return (EINVAL);
  908                 }
  909         }
  910 
  911         switch (((struct sadb_msg *)headers[0])->sadb_msg_type) {
  912         case SADB_UPDATE:
  913                 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state !=
  914                     SADB_SASTATE_MATURE) {
  915                         DPRINTF("updating non-mature SA prohibited");
  916                         return (EINVAL);
  917                 }
  918                 break;
  919         case SADB_ADD:
  920                 if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state !=
  921                     SADB_SASTATE_MATURE) {
  922                         DPRINTF("adding non-mature SA prohibited");
  923                         return (EINVAL);
  924                 }
  925                 break;
  926         }
  927 
  928         return (0);
  929 }

Cache object: bb8097d9ca3386b1ef788ed5d073c627


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.