/** Decode SIM/AKA/AKA' attributes * * @param[in] ctx to allocate attributes in. * @param[in] cursor where to insert the attributes. * @param[in] dict for looking up attributes. * @param[in] data data to parse. * @param[in] data_len length of data. For top level attributes packet_ctx must be the length * of the packet (so we can hunt for AT_IV), for Sub-TLVs it should * be the length of the container value. * @param[in] decoder_ctx extra context to pass to the decoder. * @return * - The number of bytes parsed. * - -1 on error. */ ssize_t fr_sim_decode_pair(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const *dict, uint8_t const *data, size_t data_len, void *decoder_ctx) { return sim_decode_pair_internal(ctx, cursor, fr_dict_root(dict), data, data_len, decoder_ctx); }
/* * build a reply to be sent. */ static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra, size_t hmac_extra_len) { eap_sim_session_t *eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t); fr_cursor_t cursor; fr_cursor_t to_encode; VALUE_PAIR *head = NULL, *vp; REQUEST *request = eap_session->request; fr_sim_encode_ctx_t encoder_ctx = { .root = fr_dict_root(dict_eap_sim), .keys = &eap_sim_session->keys, .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, .iv_included = false, .hmac_md = EVP_sha1(), .eap_packet = eap_session->this_round->request, .hmac_extra = hmac_extra, .hmac_extra_len = hmac_extra_len }; ssize_t ret; /* we will set the ID on requests, since we have to HMAC it */ eap_session->this_round->set_request_id = true; fr_cursor_init(&cursor, &eap_session->request->reply->vps); fr_cursor_init(&to_encode, &head); while ((vp = fr_cursor_current(&cursor))) { if (!fr_dict_parent_common(fr_dict_root(dict_eap_sim), vp->da, true)) { fr_cursor_next(&cursor); continue; } vp = fr_cursor_remove(&cursor); /* * Silently discard encrypted attributes until * the peer should have k_encr. These can be * added by policy, and seem to cause * wpa_supplicant to fail if sent before the challenge. */ if (!eap_sim_session->allow_encrypted && fr_dict_parent_common(attr_eap_sim_encr_data, vp->da, true)) { RWDEBUG("Silently discarding &reply:%s: Encrypted attributes not allowed in this round", vp->da->name); talloc_free(vp); continue; } fr_cursor_append(&to_encode, vp); } RDEBUG2("Encoding EAP-SIM attributes"); log_request_pair_list(L_DBG_LVL_2, request, head, NULL); eap_session->this_round->request->type.num = FR_EAP_SIM; eap_session->this_round->request->id = eap_sim_session->sim_id++ & 0xff; eap_session->this_round->set_request_id = true; ret = fr_sim_encode(eap_session->request, head, &encoder_ctx); fr_cursor_head(&to_encode); fr_cursor_free_list(&to_encode); if (ret < 0) { RPEDEBUG("Failed encoding EAP-SIM data"); return -1; } return 0; } static int eap_sim_send_start(eap_session_t *eap_session) { REQUEST *request = eap_session->request; VALUE_PAIR **vps, *vp; uint16_t version; eap_sim_session_t *eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t); RADIUS_PACKET *packet; rad_assert(eap_session->request != NULL); rad_assert(eap_session->request->reply); RDEBUG2("Sending SIM-State"); eap_session->this_round->request->code = FR_EAP_CODE_REQUEST; eap_sim_session->allow_encrypted = false; /* In case this is after failed fast-resumption */ /* these are the outgoing attributes */ packet = eap_session->request->reply; vps = &packet->vps; rad_assert(vps != NULL); /* * Add appropriate TLVs for the EAP things we wish to send. */ vp = fr_pair_afrom_da(packet, attr_eap_sim_version_list); vp->vp_uint16 = EAP_SIM_VERSION; fr_pair_add(vps, vp); /* record it in the ess */ version = htons(EAP_SIM_VERSION); memcpy(eap_sim_session->keys.gsm.version_list, &version, sizeof(version)); eap_sim_session->keys.gsm.version_list_len = 2; /* * Select the right type of identity request attribute */ switch (eap_sim_session->id_req) { case SIM_ANY_ID_REQ: vp = fr_pair_afrom_da(packet, attr_eap_sim_any_id_req); break; case SIM_PERMANENT_ID_REQ: vp = fr_pair_afrom_da(packet, attr_eap_sim_permanent_id_req); break; case SIM_FULLAUTH_ID_REQ: vp = fr_pair_afrom_da(packet, attr_eap_sim_fullauth_id_req); break; default: rad_assert(0); } vp->vp_bool = true; fr_pair_replace(vps, vp); /* the SUBTYPE, set to start. */ vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype); vp->vp_uint16 = EAP_SIM_START; fr_pair_replace(vps, vp); /* * Encode the packet */ if (eap_sim_compose(eap_session, NULL, 0) < 0) { fr_pair_list_free(&packet->vps); return -1; } return 0; }