LCOV - code coverage report
Current view: top level - src/eap_common - eap_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388338050 Lines: 52 66 78.8 %
Date: 2013-12-29 Functions: 6 6 100.0 %
Branches: 21 34 61.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * EAP common peer/server definitions
       3                 :            :  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
       4                 :            :  *
       5                 :            :  * This software may be distributed under the terms of the BSD license.
       6                 :            :  * See README for more details.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include "includes.h"
      10                 :            : 
      11                 :            : #include "common.h"
      12                 :            : #include "eap_defs.h"
      13                 :            : #include "eap_common.h"
      14                 :            : 
      15                 :            : /**
      16                 :            :  * eap_hdr_len_valid - Validate EAP header length field
      17                 :            :  * @msg: EAP frame (starting with EAP header)
      18                 :            :  * @min_payload: Minimum payload length needed
      19                 :            :  * Returns: 1 for valid header, 0 for invalid
      20                 :            :  *
      21                 :            :  * This is a helper function that does minimal validation of EAP messages. The
      22                 :            :  * length field is verified to be large enough to include the header and not
      23                 :            :  * too large to go beyond the end of the buffer.
      24                 :            :  */
      25                 :       3192 : int eap_hdr_len_valid(const struct wpabuf *msg, size_t min_payload)
      26                 :            : {
      27                 :            :         const struct eap_hdr *hdr;
      28                 :            :         size_t len;
      29                 :            : 
      30         [ -  + ]:       3192 :         if (msg == NULL)
      31                 :          0 :                 return 0;
      32                 :            : 
      33                 :       3192 :         hdr = wpabuf_head(msg);
      34                 :            : 
      35         [ -  + ]:       3192 :         if (wpabuf_len(msg) < sizeof(*hdr)) {
      36                 :          0 :                 wpa_printf(MSG_INFO, "EAP: Too short EAP frame");
      37                 :          0 :                 return 0;
      38                 :            :         }
      39                 :            : 
      40                 :       3192 :         len = be_to_host16(hdr->length);
      41 [ +  - ][ -  + ]:       3192 :         if (len < sizeof(*hdr) + min_payload || len > wpabuf_len(msg)) {
      42                 :          0 :                 wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
      43                 :          0 :                 return 0;
      44                 :            :         }
      45                 :            : 
      46                 :       3192 :         return 1;
      47                 :            : }
      48                 :            : 
      49                 :            : 
      50                 :            : /**
      51                 :            :  * eap_hdr_validate - Validate EAP header
      52                 :            :  * @vendor: Expected EAP Vendor-Id (0 = IETF)
      53                 :            :  * @eap_type: Expected EAP type number
      54                 :            :  * @msg: EAP frame (starting with EAP header)
      55                 :            :  * @plen: Pointer to variable to contain the returned payload length
      56                 :            :  * Returns: Pointer to EAP payload (after type field), or %NULL on failure
      57                 :            :  *
      58                 :            :  * This is a helper function for EAP method implementations. This is usually
      59                 :            :  * called in the beginning of struct eap_method::process() function to verify
      60                 :            :  * that the received EAP request packet has a valid header. This function is
      61                 :            :  * able to process both legacy and expanded EAP headers and in most cases, the
      62                 :            :  * caller can just use the returned payload pointer (into *plen) for processing
      63                 :            :  * the payload regardless of whether the packet used the expanded EAP header or
      64                 :            :  * not.
      65                 :            :  */
      66                 :       1614 : const u8 * eap_hdr_validate(int vendor, EapType eap_type,
      67                 :            :                             const struct wpabuf *msg, size_t *plen)
      68                 :            : {
      69                 :            :         const struct eap_hdr *hdr;
      70                 :            :         const u8 *pos;
      71                 :            :         size_t len;
      72                 :            : 
      73         [ -  + ]:       1614 :         if (!eap_hdr_len_valid(msg, 1))
      74                 :          0 :                 return NULL;
      75                 :            : 
      76                 :       1614 :         hdr = wpabuf_head(msg);
      77                 :       1614 :         len = be_to_host16(hdr->length);
      78                 :       1614 :         pos = (const u8 *) (hdr + 1);
      79                 :            : 
      80         [ +  + ]:       1614 :         if (*pos == EAP_TYPE_EXPANDED) {
      81                 :            :                 int exp_vendor;
      82                 :            :                 u32 exp_type;
      83         [ -  + ]:        958 :                 if (len < sizeof(*hdr) + 8) {
      84                 :          0 :                         wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "
      85                 :            :                                    "length");
      86                 :          0 :                         return NULL;
      87                 :            :                 }
      88                 :        958 :                 pos++;
      89                 :        958 :                 exp_vendor = WPA_GET_BE24(pos);
      90                 :        958 :                 pos += 3;
      91                 :        958 :                 exp_type = WPA_GET_BE32(pos);
      92                 :        958 :                 pos += 4;
      93 [ +  - ][ -  + ]:        958 :                 if (exp_vendor != vendor || exp_type != (u32) eap_type) {
      94                 :          0 :                         wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "
      95                 :            :                                    "type");
      96                 :          0 :                         return NULL;
      97                 :            :                 }
      98                 :            : 
      99                 :        958 :                 *plen = len - sizeof(*hdr) - 8;
     100                 :        958 :                 return pos;
     101                 :            :         } else {
     102 [ +  - ][ -  + ]:        656 :                 if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {
     103                 :          0 :                         wpa_printf(MSG_INFO, "EAP: Invalid frame type");
     104                 :          0 :                         return NULL;
     105                 :            :                 }
     106                 :        656 :                 *plen = len - sizeof(*hdr) - 1;
     107                 :       1614 :                 return pos + 1;
     108                 :            :         }
     109                 :            : }
     110                 :            : 
     111                 :            : 
     112                 :            : /**
     113                 :            :  * eap_msg_alloc - Allocate a buffer for an EAP message
     114                 :            :  * @vendor: Vendor-Id (0 = IETF)
     115                 :            :  * @type: EAP type
     116                 :            :  * @payload_len: Payload length in bytes (data after Type)
     117                 :            :  * @code: Message Code (EAP_CODE_*)
     118                 :            :  * @identifier: Identifier
     119                 :            :  * Returns: Pointer to the allocated message buffer or %NULL on error
     120                 :            :  *
     121                 :            :  * This function can be used to allocate a buffer for an EAP message and fill
     122                 :            :  * in the EAP header. This function is automatically using expanded EAP header
     123                 :            :  * if the selected Vendor-Id is not IETF. In other words, most EAP methods do
     124                 :            :  * not need to separately select which header type to use when using this
     125                 :            :  * function to allocate the message buffers. The returned buffer has room for
     126                 :            :  * payload_len bytes and has the EAP header and Type field already filled in.
     127                 :            :  */
     128                 :       1312 : struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len,
     129                 :            :                               u8 code, u8 identifier)
     130                 :            : {
     131                 :            :         struct wpabuf *buf;
     132                 :            :         struct eap_hdr *hdr;
     133                 :            :         size_t len;
     134                 :            : 
     135         [ +  + ]:       1312 :         len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +
     136                 :            :                 payload_len;
     137                 :       1312 :         buf = wpabuf_alloc(len);
     138         [ -  + ]:       1312 :         if (buf == NULL)
     139                 :          0 :                 return NULL;
     140                 :            : 
     141                 :       1312 :         hdr = wpabuf_put(buf, sizeof(*hdr));
     142                 :       1312 :         hdr->code = code;
     143                 :       1312 :         hdr->identifier = identifier;
     144                 :       1312 :         hdr->length = host_to_be16(len);
     145                 :            : 
     146         [ +  + ]:       1312 :         if (vendor == EAP_VENDOR_IETF) {
     147                 :        614 :                 wpabuf_put_u8(buf, type);
     148                 :            :         } else {
     149                 :        698 :                 wpabuf_put_u8(buf, EAP_TYPE_EXPANDED);
     150                 :        698 :                 wpabuf_put_be24(buf, vendor);
     151                 :        698 :                 wpabuf_put_be32(buf, type);
     152                 :            :         }
     153                 :            : 
     154                 :       1312 :         return buf;
     155                 :            : }
     156                 :            : 
     157                 :            : 
     158                 :            : /**
     159                 :            :  * eap_update_len - Update EAP header length
     160                 :            :  * @msg: EAP message from eap_msg_alloc
     161                 :            :  *
     162                 :            :  * This function updates the length field in the EAP header to match with the
     163                 :            :  * current length for the buffer. This allows eap_msg_alloc() to be used to
     164                 :            :  * allocate a larger buffer than the exact message length (e.g., if exact
     165                 :            :  * message length is not yet known).
     166                 :            :  */
     167                 :         20 : void eap_update_len(struct wpabuf *msg)
     168                 :            : {
     169                 :            :         struct eap_hdr *hdr;
     170                 :         20 :         hdr = wpabuf_mhead(msg);
     171         [ -  + ]:         20 :         if (wpabuf_len(msg) < sizeof(*hdr))
     172                 :         20 :                 return;
     173                 :         20 :         hdr->length = host_to_be16(wpabuf_len(msg));
     174                 :            : }
     175                 :            : 
     176                 :            : 
     177                 :            : /**
     178                 :            :  * eap_get_id - Get EAP Identifier from wpabuf
     179                 :            :  * @msg: Buffer starting with an EAP header
     180                 :            :  * Returns: The Identifier field from the EAP header
     181                 :            :  */
     182                 :       1072 : u8 eap_get_id(const struct wpabuf *msg)
     183                 :            : {
     184                 :            :         const struct eap_hdr *eap;
     185                 :            : 
     186         [ -  + ]:       1072 :         if (wpabuf_len(msg) < sizeof(*eap))
     187                 :          0 :                 return 0;
     188                 :            : 
     189                 :       1072 :         eap = wpabuf_head(msg);
     190                 :       1072 :         return eap->identifier;
     191                 :            : }
     192                 :            : 
     193                 :            : 
     194                 :            : /**
     195                 :            :  * eap_get_id - Get EAP Type from wpabuf
     196                 :            :  * @msg: Buffer starting with an EAP header
     197                 :            :  * Returns: The EAP Type after the EAP header
     198                 :            :  */
     199                 :        423 : EapType eap_get_type(const struct wpabuf *msg)
     200                 :            : {
     201         [ +  + ]:        423 :         if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1)
     202                 :         52 :                 return EAP_TYPE_NONE;
     203                 :            : 
     204                 :        423 :         return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)];
     205                 :            : }

Generated by: LCOV version 1.9