📄 radius_attribute.c
字号:
/* radius_attribute.c *//* Implementation of functions to verify the validity of RADIUS attributes, *//* and to read and write RADIUS attributes from/to RADIUS packets. *//* Copyright 1984 - 2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history____________________01d,26aug03,snd Changes done to remove Compilation warnings01c,22mar02,md concatenate multiple EAP Message attributes upon received from RADIUS server into one EAP packet data01b,27feb02,md bug fixes01a,19dec00,md merged from visual source safe*//************************************************************************//* Copyright (C) 1993 - 1999 RouterWare, Inc. *//* Unpublished - rights reserved under the Copyright Laws of the *//* United States. Use, duplication, or disclosure by the *//* Government is subject to restrictions as set forth in *//* subparagraph (c)(1)(ii) of the Rights in Technical Data and *//* Computer Software clause at 252.227-7013. *//* RouterWare, Inc., 3961 MacArthur Suite 212 Newport Beach, CA 92660 *//************************************************************************/#include <ctype.h>#include <stdio.h>#include <string.h>#include "radius.h"#include "attribute_control_structures.h"/************************************************************************************************/static ATTRIBUTE_CONTROL *radius_get_attribute_control_table (enum RADIUS_CODE code);static enum TEST radius_check_attribute (ATTRIBUTE_CONTROL *sptr_attribute_control, ATTRIBUTE_COUNT *sptr_attribute_count, UINT index);static enum TEST radius_verify_modifier (ATTRIBUTE_CONTROL *sptr_attribute_control, ATTRIBUTE_COUNT *attribute_count, UINT index);static void convert_bytes_to_printable_ascii (BYTE *bptr_input_buffer, UINT length, char *cptr_output_buffer);#ifdef __EAP__static enum TEST radius_read_eap_attributes_from_packet (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *sptr_attribute_entry_in_packet, UINT packet_length, RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller);#endif /* __EAP__ */#ifdef __RADIUS_ATTRIBUTE_VERIFICATION_DEBUG__bool radius_verify_attribute_value (RADIUS_ATTRIBUTE_ENTRY* p_attribute);#endif /*__RADIUS_ATTRIBUTE_VERIFICATION_DEBUG__*//************************************************************************************************* radius_verify_attributes () verifies that the attributes in response packet comply with draft rfc. Verification algorithm: 1: Scan attribute list, getting attribute type, and count. 2: Scan the attribute table. For each attribute check the following switch (presence) ILLEGAL - if attribute in list, error ZERO OR MORE - if not present, check modifier alternate if present, check modifier both and dependent ONLY_ONE - self explanatory ONE_OR_MORE - self explanatory ************************************************************************************************/bool radius_verify_attributes (enum RADIUS_CODE code, RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller){ ATTRIBUTE_COUNT attribute_count; ATTRIBUTE_CONTROL *sptr_attribute_control; RADIUS_ATTRIBUTE_ENTRY* p_attribute; ULONG accounting_status; UINT index; RW_CONTAINER_ITERATOR attribute_iterator; sptr_attribute_control = NULL; p_attribute = NULL; attribute_iterator = 0; sptr_attribute_control = radius_get_attribute_control_table (code); if (sptr_attribute_control == NULL) { return (true); } memset (&attribute_count, 0, sizeof (UINT) * MAXIMUM_RADIUS_ATTRIBUTE_TYPE); attribute_iterator = p_radius_attribute_list_controller->iterator; rw_container_goto_front (attribute_iterator); while (rw_container_is_at_end (attribute_iterator) == false) { p_attribute = rw_container_at (attribute_iterator);#ifdef __RADIUS_ATTRIBUTE_VERIFICATION_DEBUG__ if (radius_verify_attribute_value (p_attribute) == false) { radius_printf (RADIUS_ALARM_PRINTF, "RADIUS: radius_verify_attribute_value: Value of attribute %d invalid.\n", p_attribute->type); return (false); } radius_printf (RADIUS_ALARM_PRINTF, "RADIUS: radius_verify_attribute_value: Value of attribute %d valid.\n", p_attribute->type);#endif /*__RADIUS_ATTRIBUTE_VERIFICATION_DEBUG__*/ if (p_attribute->type == RADIUS_ACCT_STATUS_TYPE) { radius_util_deserialize_ulong (p_attribute->value, &accounting_status); if ((code == RADIUS_ACCOUNTING_REQUEST) && (accounting_status > RADIUS_ACCOUNTING_OFF)) { return (true); /*Will not check tunnel accounting attributes.*/ } } attribute_count.count[p_attribute->type]++; rw_container_next (attribute_iterator); } for (index = 0; index < MAXIMUM_RADIUS_ATTRIBUTE_TYPE; ++index) { if (radius_check_attribute (sptr_attribute_control, &attribute_count, index) == FAIL) { return (false); } } return (true);} /*****************************************************************************/static ATTRIBUTE_CONTROL *radius_get_attribute_control_table (enum RADIUS_CODE code){ switch (code) { case RADIUS_ACCESS_REQUEST: return (access_request_control); case RADIUS_ACCESS_ACCEPT: return (access_accept_control); case RADIUS_ACCESS_REJECT: return (access_reject_control); case RADIUS_ACCOUNTING_REQUEST: return (accounting_request_control); case RADIUS_ACCOUNTING_RESPONSE: return (accounting_response_control); case RADIUS_ACCESS_CHALLENGE: return (access_challenge_control); case RADIUS_STATUS_SERVER: case RADIUS_STATUS_CLIENT: case RADIUS_RESERVED: default: return (NULL); }}/***************************************************************************/static enum TEST radius_check_attribute (ATTRIBUTE_CONTROL *sptr_attribute_control, ATTRIBUTE_COUNT *sptr_attribute_count, UINT index){ switch (sptr_attribute_control[index].presence) { case ILLEGAL: if (sptr_attribute_count->count[index] != ZERO_ATTRIBUTE_COUNT) { return (FAIL); } break; case ZERO_OR_MORE: if (radius_verify_modifier (sptr_attribute_control, sptr_attribute_count, index) == FAIL) { return (FAIL); } break; case ZERO_OR_ONE: if (sptr_attribute_count->count[index] > MINIMUM_ATTRIBUTE_COUNT) { return (FAIL); } break; case ONE_ONLY: if (sptr_attribute_count->count[index] != MINIMUM_ATTRIBUTE_COUNT) { return (FAIL); } break; case ONE_OR_MORE: if (sptr_attribute_count->count[index] == ZERO_ATTRIBUTE_COUNT) { return (FAIL); } break; default: /* compiler error if we get here. Table not formed well */ break; } return (PASS);}/***************************************************************************/static enum TEST radius_verify_modifier (ATTRIBUTE_CONTROL *sptr_attribute_control, ATTRIBUTE_COUNT *sptr_attribute_count, UINT index){ switch (sptr_attribute_control[index].modifier) { case NO_MODIFIER: break; case ALTERNATE: if (sptr_attribute_count->count[index] != ZERO_ATTRIBUTE_COUNT) { break; } if (sptr_attribute_count->count[sptr_attribute_control[index].other_type] == ZERO_ATTRIBUTE_COUNT) { return (FAIL); } break; case BOTH: if ((sptr_attribute_count->count[index] == ZERO_ATTRIBUTE_COUNT) || (sptr_attribute_count->count[sptr_attribute_control[index].other_type] == ZERO_ATTRIBUTE_COUNT)) { return (FAIL); } break; default: break; } return (PASS);}/*****************************************************************************************/UINT get_radius_attribute_list_length (RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller){ UINT length; RW_CONTAINER_ITERATOR attribute_iterator; RADIUS_ATTRIBUTE_ENTRY *p_attribute; length = 0; if (p_radius_attribute_list_controller == NULL) { return (0); } attribute_iterator = p_radius_attribute_list_controller->iterator; rw_container_goto_front (attribute_iterator); while (rw_container_is_at_end (attribute_iterator) == false) { p_attribute = rw_container_at (attribute_iterator); length += (p_attribute->length_of_attribute_value + RADIUS_SIZE_OF_ATTRIBUTE_HEADER_IN_PACKET); rw_container_next (attribute_iterator); } return (length);}/*****************************************************************************************/enum TEST radius_write_attributes_to_packet (RADIUS_PACKET *sptr_packet, RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller){ RW_CONTAINER_ITERATOR attribute_iterator; RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *sptr_attribute_entry_in_packet; RADIUS_ATTRIBUTE_ENTRY* p_attribute; if (sptr_packet == NULL) { return (FAIL); } sptr_attribute_entry_in_packet = (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *) &sptr_packet->data; attribute_iterator = p_radius_attribute_list_controller->iterator; rw_container_goto_front (attribute_iterator); while (rw_container_is_at_end (attribute_iterator) == false) { p_attribute = rw_container_at (attribute_iterator); sptr_attribute_entry_in_packet->type = (BYTE_ENUM (RADIUS_ATTRIBUTE_TYPE)) p_attribute->type; sptr_attribute_entry_in_packet->length = (BYTE) (p_attribute->length_of_attribute_value + RADIUS_SIZE_OF_ATTRIBUTE_HEADER_IN_PACKET); memcpy (&sptr_attribute_entry_in_packet->value[0], &p_attribute->value[0], p_attribute->length_of_attribute_value); sptr_attribute_entry_in_packet = (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *) ((BYTE *) sptr_attribute_entry_in_packet + sptr_attribute_entry_in_packet->length); rw_container_next (attribute_iterator); } return (PASS);}/*****************************************************************************************/enum TEST radius_read_attributes_from_packet (RADIUS_PACKET *sptr_packet, RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller){#ifndef __EAP__ enum RADIUS_ATTRIBUTE_TYPE type; UINT attribute_length;#endif /* __EAP__ */ RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *sptr_attribute_entry_in_packet; UINT packet_length; if (sptr_packet == NULL) { return (FAIL); } if (p_radius_attribute_list_controller == NULL) { return (FAIL); } sptr_attribute_entry_in_packet = (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *) &sptr_packet->data; packet_length = (UINT) (swap (sptr_packet->header.length)); if (packet_length < sizeof (RADIUS_PACKET_HEADER)) { return (FAIL); } packet_length -= sizeof (RADIUS_PACKET_HEADER);#ifdef __EAP__ if (radius_read_eap_attributes_from_packet (sptr_attribute_entry_in_packet, packet_length, p_radius_attribute_list_controller) == FAIL) { return (FAIL); }#else while (packet_length > 0) { type = sptr_attribute_entry_in_packet->type; attribute_length = (UINT) sptr_attribute_entry_in_packet->length; packet_length -= attribute_length; if (radius_add_attribute_to_list ((RADIUS_ATTRIBUTE_LIST_HANDLE) p_radius_attribute_list_controller, type, attribute_length - RADIUS_SIZE_OF_ATTRIBUTE_HEADER_IN_PACKET, &sptr_attribute_entry_in_packet->value[0]) == FAIL) { return (FAIL); } sptr_attribute_entry_in_packet = (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *) ((UINT) sptr_attribute_entry_in_packet + attribute_length); }#endif /* __EAP__ */ return (PASS);}#ifdef __EAP__/*****************************************************************************************//* Read EAP Message attributes from the packet and concatenate them into one *//* consecutive data buffer before adding them to the attribute list handle if *//* necessary. *//*****************************************************************************************/static enum TEST radius_read_eap_attributes_from_packet (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *sptr_attribute_entry_in_packet, UINT packet_length, RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller){ enum RADIUS_ATTRIBUTE_TYPE type; UINT attribute_length; UINT length_of_attribute_data; BYTE temp_attribute_data[MAXIMUM_RADIUS_RX_PACKET_SIZE]; bool eap_message_found = false; int index = 0; while (packet_length > 0) { type = sptr_attribute_entry_in_packet->type; attribute_length = (UINT) sptr_attribute_entry_in_packet->length; length_of_attribute_data = attribute_length - RADIUS_SIZE_OF_ATTRIBUTE_HEADER_IN_PACKET; if (type == RADIUS_EAP_MESSAGE) { memcpy (&temp_attribute_data[index], &sptr_attribute_entry_in_packet->value[0], length_of_attribute_data); index += length_of_attribute_data; eap_message_found = true; } else { if (eap_message_found == true) { if (radius_add_attribute_to_list ((RADIUS_ATTRIBUTE_LIST_HANDLE) p_radius_attribute_list_controller, RADIUS_EAP_MESSAGE, index, &temp_attribute_data[0]) == FAIL) { return (FAIL); } index = 0; eap_message_found = false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -