mirror of https://github.com/ARMmbed/mbed-os.git
260 lines
6.5 KiB
C
260 lines
6.5 KiB
C
/*
|
|
* Copyright (c) 2020, Pelion and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "nsconfig.h"
|
|
#include "ns_types.h"
|
|
#include "eventOS_event.h"
|
|
#include "ns_trace.h"
|
|
#include "string.h"
|
|
#include "common_functions.h"
|
|
#include "Security/protocols/radius_sec_prot/avp_helper.h"
|
|
|
|
#ifdef HAVE_WS
|
|
|
|
#define TRACE_GROUP "avp"
|
|
|
|
// RFC 2865
|
|
|
|
// 1 User-Name
|
|
#define AVP_TYPE_USER_NAME 1
|
|
// 4 for NAS-IP-Address
|
|
#define AVP_TYPE_NAS_IP_ADDRESS 4
|
|
// 5 NAS-Port
|
|
#define AVP_TYPE_NAS_PORT 5
|
|
// 12 Framed-MTU
|
|
#define AVP_TYPE_FRAMED_MTU 12
|
|
// 24 State
|
|
#define AVP_TYPE_STATE 24
|
|
// 26 Vendor-Specific
|
|
#define AVP_TYPE_VENDOR_SPECIFIC 26
|
|
// 30 Called-Station-Id
|
|
#define AVP_TYPE_CALLED_STATION_ID 30
|
|
// 31 Calling-Station-Id
|
|
#define AVP_TYPE_CALLING_STATION_ID 31
|
|
// 32 NAS-Identifier
|
|
#define AVP_TYPE_NAS_IDENTIFIER 32
|
|
// 61 NAS-Port-Type
|
|
#define AVP_TYPE_NAS_PORT_TYPE 61
|
|
|
|
// RFC 3579
|
|
|
|
// 79 EAP-Message
|
|
#define AVP_TYPE_EAP_MESSAGE 79
|
|
// 80 Message-Authenticator
|
|
#define AVP_TYPE_MESSAGE_AUTHENTICATOR 80
|
|
|
|
// RFC 3162
|
|
|
|
// 95 NAS-IPv6-Address
|
|
#define AVP_TYPE_NAS_IPV6_ADDRESS 95
|
|
|
|
|
|
static uint8_t *avp_header_write(uint8_t *ptr, const uint8_t type, const uint8_t data_length)
|
|
{
|
|
*ptr++ = type;
|
|
*ptr++ = data_length + AVP_FIXED_LEN;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
static uint8_t *avp_search(uint8_t *ptr, uint16_t len, const uint8_t type, uint8_t *avp_len)
|
|
{
|
|
while (len >= AVP_FIXED_LEN) {
|
|
*avp_len = ptr[1];
|
|
|
|
// Validates length field
|
|
if (*avp_len > len) {
|
|
return NULL;
|
|
}
|
|
|
|
if (ptr[0] == type) {
|
|
return ptr + AVP_FIXED_LEN;
|
|
}
|
|
|
|
if (len > *avp_len) {
|
|
len -= *avp_len;
|
|
ptr += *avp_len;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static uint8_t *avp_vpa_search(uint8_t *ptr, uint16_t len, const uint32_t vendor_id, const uint8_t vendor_type, uint8_t *vendor_len)
|
|
{
|
|
uint8_t avp_len = 0;
|
|
|
|
while (len >= AVP_FIXED_LEN) {
|
|
avp_len = ptr[1];
|
|
|
|
// Validates length field
|
|
if (avp_len > len) {
|
|
return NULL;
|
|
}
|
|
|
|
if (ptr[0] == AVP_TYPE_VENDOR_SPECIFIC && avp_len >= 9) {
|
|
ptr[2] = 0;
|
|
uint32_t avp_vendor_id = common_read_32_bit(&ptr[2]);
|
|
*vendor_len = ptr[7];
|
|
if (avp_vendor_id == vendor_id && ptr[6] == vendor_type) {
|
|
return &ptr[8];
|
|
}
|
|
}
|
|
|
|
if (len > avp_len) {
|
|
len -= avp_len;
|
|
ptr += avp_len;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
uint8_t *avp_user_name_write(uint8_t *ptr, const uint8_t name_len, const uint8_t *name)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_USER_NAME, name_len);
|
|
memcpy(ptr, name, name_len);
|
|
return ptr + name_len;
|
|
}
|
|
|
|
uint8_t *avp_nas_ip_address_write(uint8_t *ptr, uint32_t addr)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IP_ADDRESS, 4);
|
|
memcpy(ptr, &addr, 4);
|
|
return ptr + 4;
|
|
}
|
|
|
|
uint8_t *avp_nas_port_write(uint8_t *ptr, const uint32_t port)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_PORT, 4);
|
|
ptr = common_write_32_bit(port, ptr);
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_framed_mtu_write(uint8_t *ptr, const uint32_t mtu)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_FRAMED_MTU, 4);
|
|
ptr = common_write_32_bit(mtu, ptr);
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_state_write(uint8_t *ptr, const uint8_t state_len, const uint8_t *state)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_STATE, state_len);
|
|
memcpy(ptr, state, state_len);
|
|
return ptr + state_len;
|
|
}
|
|
|
|
uint8_t *avp_called_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_CALLED_STATION_ID, id_len);
|
|
memcpy(ptr, id, id_len);
|
|
return ptr + id_len;
|
|
}
|
|
|
|
uint8_t *avp_calling_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_CALLING_STATION_ID, id_len);
|
|
memcpy(ptr, id, id_len);
|
|
return ptr + id_len;
|
|
}
|
|
|
|
uint8_t *avp_nas_identifier_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IDENTIFIER, id_len);
|
|
memcpy(ptr, id, id_len);
|
|
return ptr + id_len;
|
|
}
|
|
|
|
uint8_t *avp_nas_port_type_write(uint8_t *ptr, const uint32_t port_type)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_PORT_TYPE, 4);
|
|
ptr = common_write_32_bit(port_type, ptr);
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_eap_message_write(uint8_t *ptr, const uint8_t eap_len, const uint8_t *eap)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_EAP_MESSAGE, eap_len);
|
|
memcpy(ptr, eap, eap_len);
|
|
return ptr + eap_len;
|
|
}
|
|
|
|
uint8_t *avp_message_authenticator_write(uint8_t *ptr, const uint8_t *auth)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_MESSAGE_AUTHENTICATOR, 16);
|
|
memcpy(ptr, auth, 16);
|
|
return ptr + 16;
|
|
}
|
|
|
|
uint8_t *avp_nas_ipv6_address_write(uint8_t *ptr, const uint8_t *address)
|
|
{
|
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IPV6_ADDRESS, 16);
|
|
memcpy(ptr, address, 16);
|
|
return ptr + 16;
|
|
}
|
|
|
|
uint8_t *avp_eap_message_read(uint8_t *ptr, uint16_t len, uint8_t *eap_len)
|
|
{
|
|
ptr = avp_search(ptr, len, AVP_TYPE_EAP_MESSAGE, eap_len);
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_message_authenticator_read(uint8_t *ptr, uint16_t len)
|
|
{
|
|
uint8_t auth_len = 0;
|
|
ptr = avp_search(ptr, len, AVP_TYPE_MESSAGE_AUTHENTICATOR, &auth_len);
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
if (auth_len < 18) {
|
|
return NULL;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_state_read(uint8_t *ptr, uint16_t len, uint8_t *state_len)
|
|
{
|
|
ptr = avp_search(ptr, len, AVP_TYPE_STATE, state_len);
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *avp_vsa_ms_mppe_recv_key_read(uint8_t *ptr, uint16_t len, uint8_t *recv_key_len)
|
|
{
|
|
const uint32_t vendor_id = 311;
|
|
const uint8_t vendor_type = 17;
|
|
|
|
ptr = avp_vpa_search(ptr, len, vendor_id, vendor_type, recv_key_len);
|
|
if (ptr == NULL) {
|
|
return NULL;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
#endif
|
|
|