LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_tnc.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1388167526 Lines: 13 291 4.5 %
Date: 2013-12-27 Functions: 1 18 5.6 %
Branches: 2 134 1.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * EAP server method: EAP-TNC (Trusted Network Connect)
       3                 :            :  * Copyright (c) 2007-2010, 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_i.h"
      13                 :            : #include "tncs.h"
      14                 :            : 
      15                 :            : 
      16                 :            : struct eap_tnc_data {
      17                 :            :         enum eap_tnc_state {
      18                 :            :                 START, CONTINUE, RECOMMENDATION, FRAG_ACK, WAIT_FRAG_ACK, DONE,
      19                 :            :                 FAIL
      20                 :            :         } state;
      21                 :            :         enum { ALLOW, ISOLATE, NO_ACCESS, NO_RECOMMENDATION } recommendation;
      22                 :            :         struct tncs_data *tncs;
      23                 :            :         struct wpabuf *in_buf;
      24                 :            :         struct wpabuf *out_buf;
      25                 :            :         size_t out_used;
      26                 :            :         size_t fragment_size;
      27                 :            :         unsigned int was_done:1;
      28                 :            :         unsigned int was_fail:1;
      29                 :            : };
      30                 :            : 
      31                 :            : 
      32                 :            : /* EAP-TNC Flags */
      33                 :            : #define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80
      34                 :            : #define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40
      35                 :            : #define EAP_TNC_FLAGS_START 0x20
      36                 :            : #define EAP_TNC_VERSION_MASK 0x07
      37                 :            : 
      38                 :            : #define EAP_TNC_VERSION 1
      39                 :            : 
      40                 :            : 
      41                 :          0 : static const char * eap_tnc_state_txt(enum eap_tnc_state state)
      42                 :            : {
      43   [ #  #  #  #  :          0 :         switch (state) {
             #  #  #  # ]
      44                 :            :         case START:
      45                 :          0 :                 return "START";
      46                 :            :         case CONTINUE:
      47                 :          0 :                 return "CONTINUE";
      48                 :            :         case RECOMMENDATION:
      49                 :          0 :                 return "RECOMMENDATION";
      50                 :            :         case FRAG_ACK:
      51                 :          0 :                 return "FRAG_ACK";
      52                 :            :         case WAIT_FRAG_ACK:
      53                 :          0 :                 return "WAIT_FRAG_ACK";
      54                 :            :         case DONE:
      55                 :          0 :                 return "DONE";
      56                 :            :         case FAIL:
      57                 :          0 :                 return "FAIL";
      58                 :            :         }
      59                 :          0 :         return "??";
      60                 :            : }
      61                 :            : 
      62                 :            : 
      63                 :          0 : static void eap_tnc_set_state(struct eap_tnc_data *data,
      64                 :            :                               enum eap_tnc_state new_state)
      65                 :            : {
      66                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-TNC: %s -> %s",
      67                 :            :                    eap_tnc_state_txt(data->state),
      68                 :            :                    eap_tnc_state_txt(new_state));
      69                 :          0 :         data->state = new_state;
      70                 :          0 : }
      71                 :            : 
      72                 :            : 
      73                 :          0 : static void * eap_tnc_init(struct eap_sm *sm)
      74                 :            : {
      75                 :            :         struct eap_tnc_data *data;
      76                 :            : 
      77                 :          0 :         data = os_zalloc(sizeof(*data));
      78         [ #  # ]:          0 :         if (data == NULL)
      79                 :          0 :                 return NULL;
      80                 :          0 :         eap_tnc_set_state(data, START);
      81                 :          0 :         data->tncs = tncs_init();
      82         [ #  # ]:          0 :         if (data->tncs == NULL) {
      83                 :          0 :                 os_free(data);
      84                 :          0 :                 return NULL;
      85                 :            :         }
      86                 :            : 
      87         [ #  # ]:          0 :         data->fragment_size = sm->fragment_size > 100 ?
      88                 :          0 :                 sm->fragment_size - 98 : 1300;
      89                 :            : 
      90                 :          0 :         return data;
      91                 :            : }
      92                 :            : 
      93                 :            : 
      94                 :          0 : static void eap_tnc_reset(struct eap_sm *sm, void *priv)
      95                 :            : {
      96                 :          0 :         struct eap_tnc_data *data = priv;
      97                 :          0 :         wpabuf_free(data->in_buf);
      98                 :          0 :         wpabuf_free(data->out_buf);
      99                 :          0 :         tncs_deinit(data->tncs);
     100                 :          0 :         os_free(data);
     101                 :          0 : }
     102                 :            : 
     103                 :            : 
     104                 :          0 : static struct wpabuf * eap_tnc_build_start(struct eap_sm *sm,
     105                 :            :                                            struct eap_tnc_data *data, u8 id)
     106                 :            : {
     107                 :            :         struct wpabuf *req;
     108                 :            : 
     109                 :          0 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, EAP_CODE_REQUEST,
     110                 :            :                             id);
     111         [ #  # ]:          0 :         if (req == NULL) {
     112                 :          0 :                 wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory for "
     113                 :            :                            "request");
     114                 :          0 :                 eap_tnc_set_state(data, FAIL);
     115                 :          0 :                 return NULL;
     116                 :            :         }
     117                 :            : 
     118                 :          0 :         wpabuf_put_u8(req, EAP_TNC_FLAGS_START | EAP_TNC_VERSION);
     119                 :            : 
     120                 :          0 :         eap_tnc_set_state(data, CONTINUE);
     121                 :            : 
     122                 :          0 :         return req;
     123                 :            : }
     124                 :            : 
     125                 :            : 
     126                 :          0 : static struct wpabuf * eap_tnc_build(struct eap_sm *sm,
     127                 :            :                                      struct eap_tnc_data *data)
     128                 :            : {
     129                 :            :         struct wpabuf *req;
     130                 :            :         u8 *rpos, *rpos1;
     131                 :            :         size_t rlen;
     132                 :            :         char *start_buf, *end_buf;
     133                 :            :         size_t start_len, end_len;
     134                 :            :         size_t imv_len;
     135                 :            : 
     136                 :          0 :         imv_len = tncs_total_send_len(data->tncs);
     137                 :            : 
     138                 :          0 :         start_buf = tncs_if_tnccs_start(data->tncs);
     139         [ #  # ]:          0 :         if (start_buf == NULL)
     140                 :          0 :                 return NULL;
     141                 :          0 :         start_len = os_strlen(start_buf);
     142                 :          0 :         end_buf = tncs_if_tnccs_end();
     143         [ #  # ]:          0 :         if (end_buf == NULL) {
     144                 :          0 :                 os_free(start_buf);
     145                 :          0 :                 return NULL;
     146                 :            :         }
     147                 :          0 :         end_len = os_strlen(end_buf);
     148                 :            : 
     149                 :          0 :         rlen = start_len + imv_len + end_len;
     150                 :          0 :         req = wpabuf_alloc(rlen);
     151         [ #  # ]:          0 :         if (req == NULL) {
     152                 :          0 :                 os_free(start_buf);
     153                 :          0 :                 os_free(end_buf);
     154                 :          0 :                 return NULL;
     155                 :            :         }
     156                 :            : 
     157                 :          0 :         wpabuf_put_data(req, start_buf, start_len);
     158                 :          0 :         os_free(start_buf);
     159                 :            : 
     160                 :          0 :         rpos1 = wpabuf_put(req, 0);
     161                 :          0 :         rpos = tncs_copy_send_buf(data->tncs, rpos1);
     162                 :          0 :         wpabuf_put(req, rpos - rpos1);
     163                 :            : 
     164                 :          0 :         wpabuf_put_data(req, end_buf, end_len);
     165                 :          0 :         os_free(end_buf);
     166                 :            : 
     167                 :          0 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Request",
     168                 :            :                           wpabuf_head(req), wpabuf_len(req));
     169                 :            : 
     170                 :          0 :         return req;
     171                 :            : }
     172                 :            : 
     173                 :            : 
     174                 :          0 : static struct wpabuf * eap_tnc_build_recommendation(struct eap_sm *sm,
     175                 :            :                                                     struct eap_tnc_data *data)
     176                 :            : {
     177   [ #  #  #  #  :          0 :         switch (data->recommendation) {
                      # ]
     178                 :            :         case ALLOW:
     179                 :          0 :                 eap_tnc_set_state(data, DONE);
     180                 :          0 :                 break;
     181                 :            :         case ISOLATE:
     182                 :          0 :                 eap_tnc_set_state(data, FAIL);
     183                 :            :                 /* TODO: support assignment to a different VLAN */
     184                 :          0 :                 break;
     185                 :            :         case NO_ACCESS:
     186                 :          0 :                 eap_tnc_set_state(data, FAIL);
     187                 :          0 :                 break;
     188                 :            :         case NO_RECOMMENDATION:
     189                 :          0 :                 eap_tnc_set_state(data, DONE);
     190                 :          0 :                 break;
     191                 :            :         default:
     192                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Unknown recommendation");
     193                 :          0 :                 return NULL;
     194                 :            :         }
     195                 :            : 
     196                 :          0 :         return eap_tnc_build(sm, data);
     197                 :            : }
     198                 :            : 
     199                 :            : 
     200                 :          0 : static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code)
     201                 :            : {
     202                 :            :         struct wpabuf *msg;
     203                 :            : 
     204                 :          0 :         msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id);
     205         [ #  # ]:          0 :         if (msg == NULL) {
     206                 :          0 :                 wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory "
     207                 :            :                            "for fragment ack");
     208                 :          0 :                 return NULL;
     209                 :            :         }
     210                 :          0 :         wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */
     211                 :            : 
     212                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack");
     213                 :            : 
     214                 :          0 :         return msg;
     215                 :            : }
     216                 :            : 
     217                 :            : 
     218                 :          0 : static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 id)
     219                 :            : {
     220                 :            :         struct wpabuf *req;
     221                 :            :         u8 flags;
     222                 :            :         size_t send_len, plen;
     223                 :            : 
     224                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Request");
     225                 :            : 
     226                 :          0 :         flags = EAP_TNC_VERSION;
     227                 :          0 :         send_len = wpabuf_len(data->out_buf) - data->out_used;
     228         [ #  # ]:          0 :         if (1 + send_len > data->fragment_size) {
     229                 :          0 :                 send_len = data->fragment_size - 1;
     230                 :          0 :                 flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS;
     231         [ #  # ]:          0 :                 if (data->out_used == 0) {
     232                 :          0 :                         flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED;
     233                 :          0 :                         send_len -= 4;
     234                 :            :                 }
     235                 :            :         }
     236                 :            : 
     237                 :          0 :         plen = 1 + send_len;
     238         [ #  # ]:          0 :         if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)
     239                 :          0 :                 plen += 4;
     240                 :          0 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen,
     241                 :            :                             EAP_CODE_REQUEST, id);
     242         [ #  # ]:          0 :         if (req == NULL)
     243                 :          0 :                 return NULL;
     244                 :            : 
     245                 :          0 :         wpabuf_put_u8(req, flags); /* Flags */
     246         [ #  # ]:          0 :         if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)
     247                 :          0 :                 wpabuf_put_be32(req, wpabuf_len(data->out_buf));
     248                 :            : 
     249                 :          0 :         wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
     250                 :            :                         send_len);
     251                 :          0 :         data->out_used += send_len;
     252                 :            : 
     253         [ #  # ]:          0 :         if (data->out_used == wpabuf_len(data->out_buf)) {
     254                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes "
     255                 :            :                            "(message sent completely)",
     256                 :            :                            (unsigned long) send_len);
     257                 :          0 :                 wpabuf_free(data->out_buf);
     258                 :          0 :                 data->out_buf = NULL;
     259                 :          0 :                 data->out_used = 0;
     260         [ #  # ]:          0 :                 if (data->was_fail)
     261                 :          0 :                         eap_tnc_set_state(data, FAIL);
     262         [ #  # ]:          0 :                 else if (data->was_done)
     263                 :          0 :                         eap_tnc_set_state(data, DONE);
     264                 :            :         } else {
     265                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes "
     266                 :            :                            "(%lu more to send)", (unsigned long) send_len,
     267                 :          0 :                            (unsigned long) wpabuf_len(data->out_buf) -
     268                 :          0 :                            data->out_used);
     269         [ #  # ]:          0 :                 if (data->state == FAIL)
     270                 :          0 :                         data->was_fail = 1;
     271         [ #  # ]:          0 :                 else if (data->state == DONE)
     272                 :          0 :                         data->was_done = 1;
     273                 :          0 :                 eap_tnc_set_state(data, WAIT_FRAG_ACK);
     274                 :            :         }
     275                 :            : 
     276                 :          0 :         return req;
     277                 :            : }
     278                 :            : 
     279                 :            : 
     280                 :          0 : static struct wpabuf * eap_tnc_buildReq(struct eap_sm *sm, void *priv, u8 id)
     281                 :            : {
     282                 :          0 :         struct eap_tnc_data *data = priv;
     283                 :            : 
     284   [ #  #  #  #  :          0 :         switch (data->state) {
                #  #  # ]
     285                 :            :         case START:
     286                 :          0 :                 tncs_init_connection(data->tncs);
     287                 :          0 :                 return eap_tnc_build_start(sm, data, id);
     288                 :            :         case CONTINUE:
     289         [ #  # ]:          0 :                 if (data->out_buf == NULL) {
     290                 :          0 :                         data->out_buf = eap_tnc_build(sm, data);
     291         [ #  # ]:          0 :                         if (data->out_buf == NULL) {
     292                 :          0 :                                 wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to "
     293                 :            :                                            "generate message");
     294                 :          0 :                                 return NULL;
     295                 :            :                         }
     296                 :          0 :                         data->out_used = 0;
     297                 :            :                 }
     298                 :          0 :                 return eap_tnc_build_msg(data, id);
     299                 :            :         case RECOMMENDATION:
     300         [ #  # ]:          0 :                 if (data->out_buf == NULL) {
     301                 :          0 :                         data->out_buf = eap_tnc_build_recommendation(sm, data);
     302         [ #  # ]:          0 :                         if (data->out_buf == NULL) {
     303                 :          0 :                                 wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to "
     304                 :            :                                            "generate recommendation message");
     305                 :          0 :                                 return NULL;
     306                 :            :                         }
     307                 :          0 :                         data->out_used = 0;
     308                 :            :                 }
     309                 :          0 :                 return eap_tnc_build_msg(data, id);
     310                 :            :         case WAIT_FRAG_ACK:
     311                 :          0 :                 return eap_tnc_build_msg(data, id);
     312                 :            :         case FRAG_ACK:
     313                 :          0 :                 return eap_tnc_build_frag_ack(id, EAP_CODE_REQUEST);
     314                 :            :         case DONE:
     315                 :            :         case FAIL:
     316                 :          0 :                 return NULL;
     317                 :            :         }
     318                 :            : 
     319                 :          0 :         return NULL;
     320                 :            : }
     321                 :            : 
     322                 :            : 
     323                 :          0 : static Boolean eap_tnc_check(struct eap_sm *sm, void *priv,
     324                 :            :                              struct wpabuf *respData)
     325                 :            : {
     326                 :          0 :         struct eap_tnc_data *data = priv;
     327                 :            :         const u8 *pos;
     328                 :            :         size_t len;
     329                 :            : 
     330                 :          0 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData,
     331                 :            :                                &len);
     332         [ #  # ]:          0 :         if (pos == NULL) {
     333                 :          0 :                 wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame");
     334                 :          0 :                 return TRUE;
     335                 :            :         }
     336                 :            : 
     337 [ #  # ][ #  # ]:          0 :         if (len == 0 && data->state != WAIT_FRAG_ACK) {
     338                 :          0 :                 wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (empty)");
     339                 :          0 :                 return TRUE;
     340                 :            :         }
     341                 :            : 
     342         [ #  # ]:          0 :         if (len == 0)
     343                 :          0 :                 return FALSE; /* Fragment ACK does not include flags */
     344                 :            : 
     345         [ #  # ]:          0 :         if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) {
     346                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d",
     347                 :          0 :                            *pos & EAP_TNC_VERSION_MASK);
     348                 :          0 :                 return TRUE;
     349                 :            :         }
     350                 :            : 
     351         [ #  # ]:          0 :         if (*pos & EAP_TNC_FLAGS_START) {
     352                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Peer used Start flag");
     353                 :          0 :                 return TRUE;
     354                 :            :         }
     355                 :            : 
     356                 :          0 :         return FALSE;
     357                 :            : }
     358                 :            : 
     359                 :            : 
     360                 :          0 : static void tncs_process(struct eap_tnc_data *data, struct wpabuf *inbuf)
     361                 :            : {
     362                 :            :         enum tncs_process_res res;
     363                 :            : 
     364                 :          0 :         res = tncs_process_if_tnccs(data->tncs, wpabuf_head(inbuf),
     365                 :            :                                     wpabuf_len(inbuf));
     366   [ #  #  #  #  :          0 :         switch (res) {
                   #  # ]
     367                 :            :         case TNCCS_RECOMMENDATION_ALLOW:
     368                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS allowed access");
     369                 :          0 :                 eap_tnc_set_state(data, RECOMMENDATION);
     370                 :          0 :                 data->recommendation = ALLOW;
     371                 :          0 :                 break;
     372                 :            :         case TNCCS_RECOMMENDATION_NO_RECOMMENDATION:
     373                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS has no recommendation");
     374                 :          0 :                 eap_tnc_set_state(data, RECOMMENDATION);
     375                 :          0 :                 data->recommendation = NO_RECOMMENDATION;
     376                 :          0 :                 break;
     377                 :            :         case TNCCS_RECOMMENDATION_ISOLATE:
     378                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS requested isolation");
     379                 :          0 :                 eap_tnc_set_state(data, RECOMMENDATION);
     380                 :          0 :                 data->recommendation = ISOLATE;
     381                 :          0 :                 break;
     382                 :            :         case TNCCS_RECOMMENDATION_NO_ACCESS:
     383                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS rejected access");
     384                 :          0 :                 eap_tnc_set_state(data, RECOMMENDATION);
     385                 :          0 :                 data->recommendation = NO_ACCESS;
     386                 :          0 :                 break;
     387                 :            :         case TNCCS_PROCESS_ERROR:
     388                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS processing error");
     389                 :          0 :                 eap_tnc_set_state(data, FAIL);
     390                 :          0 :                 break;
     391                 :            :         default:
     392                 :          0 :                 break;
     393                 :            :         }
     394                 :          0 : }
     395                 :            : 
     396                 :            : 
     397                 :          0 : static int eap_tnc_process_cont(struct eap_tnc_data *data,
     398                 :            :                                 const u8 *buf, size_t len)
     399                 :            : {
     400                 :            :         /* Process continuation of a pending message */
     401         [ #  # ]:          0 :         if (len > wpabuf_tailroom(data->in_buf)) {
     402                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow");
     403                 :          0 :                 eap_tnc_set_state(data, FAIL);
     404                 :          0 :                 return -1;
     405                 :            :         }
     406                 :            : 
     407                 :          0 :         wpabuf_put_data(data->in_buf, buf, len);
     408                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for %lu "
     409                 :            :                    "bytes more", (unsigned long) len,
     410                 :          0 :                    (unsigned long) wpabuf_tailroom(data->in_buf));
     411                 :            : 
     412                 :          0 :         return 0;
     413                 :            : }
     414                 :            : 
     415                 :            : 
     416                 :          0 : static int eap_tnc_process_fragment(struct eap_tnc_data *data,
     417                 :            :                                     u8 flags, u32 message_length,
     418                 :            :                                     const u8 *buf, size_t len)
     419                 :            : {
     420                 :            :         /* Process a fragment that is not the last one of the message */
     421 [ #  # ][ #  # ]:          0 :         if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) {
     422                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a "
     423                 :            :                            "fragmented packet");
     424                 :          0 :                 return -1;
     425                 :            :         }
     426                 :            : 
     427         [ #  # ]:          0 :         if (data->in_buf == NULL) {
     428                 :            :                 /* First fragment of the message */
     429                 :          0 :                 data->in_buf = wpabuf_alloc(message_length);
     430         [ #  # ]:          0 :                 if (data->in_buf == NULL) {
     431                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for "
     432                 :            :                                    "message");
     433                 :          0 :                         return -1;
     434                 :            :                 }
     435                 :          0 :                 wpabuf_put_data(data->in_buf, buf, len);
     436                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first "
     437                 :            :                            "fragment, waiting for %lu bytes more",
     438                 :            :                            (unsigned long) len,
     439                 :          0 :                            (unsigned long) wpabuf_tailroom(data->in_buf));
     440                 :            :         }
     441                 :            : 
     442                 :          0 :         return 0;
     443                 :            : }
     444                 :            : 
     445                 :            : 
     446                 :          0 : static void eap_tnc_process(struct eap_sm *sm, void *priv,
     447                 :            :                             struct wpabuf *respData)
     448                 :            : {
     449                 :          0 :         struct eap_tnc_data *data = priv;
     450                 :            :         const u8 *pos, *end;
     451                 :            :         size_t len;
     452                 :            :         u8 flags;
     453                 :          0 :         u32 message_length = 0;
     454                 :            :         struct wpabuf tmpbuf;
     455                 :            : 
     456                 :          0 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData, &len);
     457         [ #  # ]:          0 :         if (pos == NULL)
     458                 :          0 :                 return; /* Should not happen; message already verified */
     459                 :            : 
     460                 :          0 :         end = pos + len;
     461                 :            : 
     462 [ #  # ][ #  # ]:          0 :         if (len == 1 && (data->state == DONE || data->state == FAIL)) {
                 [ #  # ]
     463                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Peer acknowledged the last "
     464                 :            :                            "message");
     465                 :          0 :                 return;
     466                 :            :         }
     467                 :            : 
     468         [ #  # ]:          0 :         if (len == 0) {
     469                 :            :                 /* fragment ack */
     470                 :          0 :                 flags = 0;
     471                 :            :         } else
     472                 :          0 :                 flags = *pos++;
     473                 :            : 
     474         [ #  # ]:          0 :         if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) {
     475         [ #  # ]:          0 :                 if (end - pos < 4) {
     476                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow");
     477                 :          0 :                         eap_tnc_set_state(data, FAIL);
     478                 :          0 :                         return;
     479                 :            :                 }
     480                 :          0 :                 message_length = WPA_GET_BE32(pos);
     481                 :          0 :                 pos += 4;
     482                 :            : 
     483         [ #  # ]:          0 :                 if (message_length < (u32) (end - pos)) {
     484                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message "
     485                 :            :                                    "Length (%d; %ld remaining in this msg)",
     486                 :            :                                    message_length, (long) (end - pos));
     487                 :          0 :                         eap_tnc_set_state(data, FAIL);
     488                 :          0 :                         return;
     489                 :            :                 }
     490                 :            :         }
     491                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x "
     492                 :            :                    "Message Length %u", flags, message_length);
     493                 :            : 
     494         [ #  # ]:          0 :         if (data->state == WAIT_FRAG_ACK) {
     495         [ #  # ]:          0 :                 if (len > 1) {
     496                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload "
     497                 :            :                                    "in WAIT_FRAG_ACK state");
     498                 :          0 :                         eap_tnc_set_state(data, FAIL);
     499                 :          0 :                         return;
     500                 :            :                 }
     501                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged");
     502                 :          0 :                 eap_tnc_set_state(data, CONTINUE);
     503                 :          0 :                 return;
     504                 :            :         }
     505                 :            : 
     506 [ #  # ][ #  # ]:          0 :         if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) {
     507                 :          0 :                 eap_tnc_set_state(data, FAIL);
     508                 :          0 :                 return;
     509                 :            :         }
     510                 :            :                 
     511         [ #  # ]:          0 :         if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) {
     512         [ #  # ]:          0 :                 if (eap_tnc_process_fragment(data, flags, message_length,
     513                 :          0 :                                              pos, end - pos) < 0)
     514                 :          0 :                         eap_tnc_set_state(data, FAIL);
     515                 :            :                 else
     516                 :          0 :                         eap_tnc_set_state(data, FRAG_ACK);
     517                 :          0 :                 return;
     518         [ #  # ]:          0 :         } else if (data->state == FRAG_ACK) {
     519                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received");
     520                 :          0 :                 eap_tnc_set_state(data, CONTINUE);
     521                 :            :         }
     522                 :            : 
     523         [ #  # ]:          0 :         if (data->in_buf == NULL) {
     524                 :            :                 /* Wrap unfragmented messages as wpabuf without extra copy */
     525                 :          0 :                 wpabuf_set(&tmpbuf, pos, end - pos);
     526                 :          0 :                 data->in_buf = &tmpbuf;
     527                 :            :         }
     528                 :            : 
     529                 :          0 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Received payload",
     530                 :          0 :                           wpabuf_head(data->in_buf), wpabuf_len(data->in_buf));
     531                 :          0 :         tncs_process(data, data->in_buf);
     532                 :            : 
     533         [ #  # ]:          0 :         if (data->in_buf != &tmpbuf)
     534                 :          0 :                 wpabuf_free(data->in_buf);
     535                 :          0 :         data->in_buf = NULL;
     536                 :            : }
     537                 :            : 
     538                 :            : 
     539                 :          0 : static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv)
     540                 :            : {
     541                 :          0 :         struct eap_tnc_data *data = priv;
     542 [ #  # ][ #  # ]:          0 :         return data->state == DONE || data->state == FAIL;
     543                 :            : }
     544                 :            : 
     545                 :            : 
     546                 :          0 : static Boolean eap_tnc_isSuccess(struct eap_sm *sm, void *priv)
     547                 :            : {
     548                 :          0 :         struct eap_tnc_data *data = priv;
     549                 :          0 :         return data->state == DONE;
     550                 :            : }
     551                 :            : 
     552                 :            : 
     553                 :          1 : int eap_server_tnc_register(void)
     554                 :            : {
     555                 :            :         struct eap_method *eap;
     556                 :            :         int ret;
     557                 :            : 
     558                 :          1 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     559                 :            :                                       EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC");
     560         [ -  + ]:          1 :         if (eap == NULL)
     561                 :          0 :                 return -1;
     562                 :            : 
     563                 :          1 :         eap->init = eap_tnc_init;
     564                 :          1 :         eap->reset = eap_tnc_reset;
     565                 :          1 :         eap->buildReq = eap_tnc_buildReq;
     566                 :          1 :         eap->check = eap_tnc_check;
     567                 :          1 :         eap->process = eap_tnc_process;
     568                 :          1 :         eap->isDone = eap_tnc_isDone;
     569                 :          1 :         eap->isSuccess = eap_tnc_isSuccess;
     570                 :            : 
     571                 :          1 :         ret = eap_server_method_register(eap);
     572         [ -  + ]:          1 :         if (ret)
     573                 :          0 :                 eap_server_method_free(eap);
     574                 :          1 :         return ret;
     575                 :            : }

Generated by: LCOV version 1.9