mka: Fix memory leak in ieee802_1x_kay_create_live_peer() error path
[mech_eap.git] / src / pae / ieee802_1x_kay.c
index 415946f..66972fc 100644 (file)
@@ -532,14 +532,16 @@ ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
        peer->sak_used = FALSE;
        os_memcpy(&peer->sci, &participant->current_peer_sci,
                  sizeof(peer->sci));
-       dl_list_add(&participant->live_peers, &peer->list);
 
        secy_get_available_receive_sc(participant->kay, &sc_ch);
 
        rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
-       if (!rxsc)
+       if (!rxsc) {
+               os_free(peer);
                return NULL;
+       }
 
+       dl_list_add(&participant->live_peers, &peer->list);
        dl_list_add(&participant->rxsc_list, &rxsc->list);
        secy_create_receive_sc(participant->kay, rxsc);
 
@@ -682,7 +684,7 @@ ieee802_1x_mka_encode_basic_body(
 
        os_memcpy(body->actor_sci.addr, kay->actor_sci.addr,
                  sizeof(kay->actor_sci.addr));
-       body->actor_sci.port = host_to_be16(kay->actor_sci.port);
+       body->actor_sci.port = kay->actor_sci.port;
 
        os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi));
        participant->mn = participant->mn + 1;
@@ -735,10 +737,10 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg,
        }
 
        os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
-       participant->current_peer_id.mn =  be_to_host32(body->actor_mn);
+       participant->current_peer_id.mn = body->actor_mn;
        os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
                  sizeof(participant->current_peer_sci.addr));
-       participant->current_peer_sci.port = be_to_host16(body->actor_sci.port);
+       participant->current_peer_sci.port = body->actor_sci.port;
 
        /* handler peer */
        peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
@@ -2097,7 +2099,6 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
        struct ieee802_1x_kay_peer *key_server = NULL;
        struct ieee802_1x_kay *kay = participant->kay;
        Boolean i_is_key_server;
-       int i;
 
        if (participant->is_obliged_key_server) {
                participant->new_sak = TRUE;
@@ -2122,11 +2123,9 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
                        key_server = peer;
                } else if (peer->key_server_priority ==
                           key_server->key_server_priority) {
-                       for (i = 0; i < 6; i++) {
-                               if (peer->sci.addr[i] <
-                                   key_server->sci.addr[i])
-                                       key_server = peer;
-                       }
+                       if (os_memcmp(peer->sci.addr, key_server->sci.addr,
+                                     ETH_ALEN) < 0)
+                               key_server = peer;
                }
        }
 
@@ -2138,20 +2137,12 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
                        i_is_key_server = TRUE;
                } else if (kay->actor_priority
                                        == key_server->key_server_priority) {
-                       for (i = 0; i < 6; i++) {
-                               if (kay->actor_sci.addr[i]
-                                       < key_server->sci.addr[i]) {
-                                       i_is_key_server = TRUE;
-                               }
-                       }
+                       if (os_memcmp(kay->actor_sci.addr, key_server->sci.addr,
+                                     ETH_ALEN) < 0)
+                               i_is_key_server = TRUE;
                }
-       }
-
-       if (!key_server && !i_is_key_server) {
-               participant->principal = FALSE;
-               participant->is_key_server = FALSE;
-               participant->is_elected = FALSE;
-               return 0;
+       } else if (participant->can_be_key_server) {
+               i_is_key_server = TRUE;
        }
 
        if (i_is_key_server) {
@@ -2172,9 +2163,7 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
                os_memcpy(&kay->key_server_sci, &kay->actor_sci,
                          sizeof(kay->key_server_sci));
                kay->key_server_priority = kay->actor_priority;
-       }
-
-       if (key_server) {
+       } else if (key_server) {
                ieee802_1x_cp_set_electedself(kay->cp, FALSE);
                if (os_memcmp(&kay->key_server_sci, &key_server->sci,
                              sizeof(kay->key_server_sci))) {
@@ -2189,6 +2178,10 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
                os_memcpy(&kay->key_server_sci, &key_server->sci,
                          sizeof(kay->key_server_sci));
                kay->key_server_priority = key_server->key_server_priority;
+       } else {
+               participant->principal = FALSE;
+               participant->is_key_server = FALSE;
+               participant->is_elected = FALSE;
        }
 
        return 0;
@@ -3016,7 +3009,8 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
                        if (!ieee802_1x_kay_create_live_peer(
                                    participant,
                                    participant->current_peer_id.mi,
-                                   participant->current_peer_id.mn))
+                                   be_to_host32(
+                                           participant->current_peer_id.mn)))
                                return -1;
                        ieee802_1x_kay_elect_key_server(participant);
                        ieee802_1x_kay_decide_macsec_use(participant);
@@ -3025,7 +3019,7 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
                            participant, participant->current_peer_id.mi)) {
                        ieee802_1x_kay_move_live_peer(
                                participant, participant->current_peer_id.mi,
-                               participant->current_peer_id.mn);
+                               be_to_host32(participant->current_peer_id.mn));
                        ieee802_1x_kay_elect_key_server(participant);
                        ieee802_1x_kay_decide_macsec_use(participant);
                }
@@ -3152,7 +3146,7 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
 
        os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
        os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
-       kay->actor_sci.port = 0x0001;
+       kay->actor_sci.port = host_to_be16(0x0001);
        kay->actor_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
 
        /* While actor acts as a key server, shall distribute sakey */
@@ -3319,7 +3313,7 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn,
        default:
                participant->is_obliged_key_server = FALSE;
                participant->can_be_key_server = TRUE;
-               participant->is_key_server = FALSE;
+               participant->is_key_server = TRUE;
                participant->is_elected = FALSE;
                break;
        }