📄 radius_rx.c
字号:
/* radius_rx.c *//* Implementations of fucntions that handle the receipt of RADIUS packets. *//* Copyright 1984 - 2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history____________________Date Init Change description031102 md Enhancement - moving polling socket read to seperate tasks and replace taskLock/unLock with rwos_radius_data_mutex030402 md Add support for EAP030402 md Bug fix - authenticate accounting response when verify response authenticator is enable111401 md Fixed SPR#70426 - pool packet identifiers per server092701 md Fixed SPR#70639 retransmission of accounting requests with RADIUS_ACCT_DELAY_TIME attribute052301 tk Added a check on user_count before deleting server in radius_process_received_packet. This check adds an extra measure of security to avoid deletion of the server while some client may have not freed the server handle it has obtained from the RADIUS Client.052101 tk Fixed Siemen's bug 18: Improved the check of server's reply to handle the possible case of authentication server sending accounting response or accounting server sending authentication response. This problem and the improved check code were done as suggested by Siemen's engineer.040501 tk Added code to handle replied packet received from back-up server.021601 tk Fixed memory leaks (SPR 64177)012601 tk ifdef all RADIUS MIBs code with __RADIUS_MIB__121900 md Fixed packet id - freeing packet id when response is received121900 md Merged from visual source safe*/#include <string.h>#include "radius.h"#ifdef __RADIUS_MIB__#include "radius_mib_include.h"#endif/***************************************************************************/extern RWOS_MUTEX rwos_radius_data_mutex;/************************************************************************/static void radius_process_received_packet (RADIUS_SERVER* p_server, RADIUS_PACKET *sptr_rx_packet);static RADIUS_SERVER * get_radius_server (struct sockaddr_in * p_remote_socket_info);/************************************************************************/void receive_radius_packet (void* p_user){ RADIUS_PACKET *sptr_rx_packet; SOCKADDR remote_sockaddr; ULONG sockaddr_length; int number_of_bytes_received; RADIUS_SOCKET_OBJECT* p_socket; struct sockaddr_in * p_remote_socket_info; RADIUS_SERVER* p_server = NULL; if (p_user == NULL) { return; } p_socket = (RADIUS_SOCKET_OBJECT*) p_user; sockaddr_length = sizeof (SOCKADDR); sptr_rx_packet = buffer_malloc (radius.maximum_rx_packet_size); if (sptr_rx_packet == NULL) { radius_printf (RADIUS_SOCKET_PRINTF, "RADIUS: receive_radius_packe: Out of memory\n"); return; } memset (sptr_rx_packet, 0, radius.maximum_rx_packet_size); number_of_bytes_received = recvfrom (p_socket->socket_descriptor, (char *) sptr_rx_packet, radius.maximum_rx_packet_size, (int) NULL, &remote_sockaddr, (int *) &sockaddr_length); if (((short) number_of_bytes_received) <= 0x0000) { buffer_free (sptr_rx_packet); radius_printf (RADIUS_SOCKET_PRINTF, "RADIUS: receive_radius_packet: No more data to read; socket %8xl,\n", p_socket->socket_descriptor); return; } else { radius_printf (RADIUS_SOCKET_PRINTF,"RADIUS Transport: Received %d bytes.\r\n", number_of_bytes_received); } p_remote_socket_info = (struct sockaddr_in *)&remote_sockaddr; rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); p_server = get_radius_server (p_remote_socket_info); if (p_server == NULL) { radius_printf (RADIUS_ALARM_PRINTF,"RADIUS Transport: Unable to get RADIUS server.\r\n"); return; } radius_process_received_packet (p_server, sptr_rx_packet); rwos_mutex_release (rwos_radius_data_mutex);}/************************************************************************/static RADIUS_SERVER * get_radius_server (struct sockaddr_in * p_remote_socket_info){ RW_CONTAINER_ITERATOR server_iterator; RADIUS_SERVER* p_server = NULL; bool found_radius_server = false; server_iterator = rw_container_create_copy_of_iterator (radius.server_controller.iterator); rw_container_goto_front (server_iterator); while (rw_container_is_at_end (server_iterator) == false) { p_server = rw_container_at (server_iterator); if ((p_server->ip_address == ntohl (p_remote_socket_info->sin_addr.s_addr)) && (p_server->port == ntohs (p_remote_socket_info->sin_port))) { found_radius_server = true; break; } rw_container_next (server_iterator); } rw_container_free_iterator (server_iterator); if (found_radius_server == true) return (p_server); else return (NULL);}/************************************************************************/static void radius_process_received_packet (RADIUS_SERVER* p_server, RADIUS_PACKET *sptr_rx_packet){ RADIUS_REQUEST_ENTRY *p_request_entry = NULL; RADIUS_ATTRIBUTE_LIST_HANDLE response_attribute_list_handle; RADIUS_LIST_CONTROLLER* p_radius_attribute_list_controller; RW_CONTAINER_ITERATOR server_iterator; RW_CONTAINER_ITERATOR request_entry_iterator; bool request_entry_found, server_unknown_response; print_radius_packet_header ("RADIUS: radius_process_received_packet", &sptr_rx_packet->header); request_entry_found = false; server_unknown_response = false; request_entry_iterator = rw_container_create_copy_of_iterator (radius.request_controller.iterator); rw_container_goto_front (request_entry_iterator); if (radius_check_packet_id_reused_pending_per_server (p_server, sptr_rx_packet->header.identifier) == false) { while (rw_container_is_at_end (request_entry_iterator) == false) { p_request_entry = rw_container_at (request_entry_iterator); if (p_request_entry->packet_header.identifier == sptr_rx_packet->header.identifier) { request_entry_found = true; break; } rw_container_next (request_entry_iterator); } } if (request_entry_found == false) { switch (sptr_rx_packet->header.code) { case RADIUS_ACCESS_ACCEPT: case RADIUS_ACCESS_REJECT: case RADIUS_ACCESS_CHALLENGE:#ifdef __RADIUS_MIB__ ++radiusAuthClientInfo.radiusAuthClientInvalidServerAddresses;#endif break; case RADIUS_ACCOUNTING_RESPONSE:#ifdef __RADIUS_MIB__ ++radiusAccClientInfo.radiusAccClientInvalidServerAddresses;#endif break; default: break; } buffer_free (sptr_rx_packet); rw_container_free_iterator (request_entry_iterator); return; } if (p_request_entry->backup_server == true) { server_iterator = (RW_CONTAINER_ITERATOR) p_request_entry->backup_server_handle; } else { server_iterator = (RW_CONTAINER_ITERATOR) p_request_entry->server_handle; } p_server = (RADIUS_SERVER*) rw_container_at (server_iterator);#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif /* Improved check header code as suggested by Siemen's engineer to * catch authentication packets sent by accounting servers and vice versa. * The remainder of the code relies on the fact that the header code * maps to the correct server type. * The server type is checked against entry p_server->type rather than * the port type of the socket where the packet is received as was done. * previously. It should make no difference. */ if (p_server->type == RADIUS_AUTHENTICATION_SERVER_TYPE) { switch (sptr_rx_packet->header.code) { case RADIUS_ACCESS_ACCEPT: ++p_server->statistics.authentication_access_accepts_rx; break; case RADIUS_ACCESS_REJECT: ++p_server->statistics.authentication_access_rejects_rx; break; case RADIUS_ACCESS_CHALLENGE: ++p_server->statistics.authentication_access_challenges_rx; break; default: ++p_server->statistics.authentication_unknown_type_packets_rx; server_unknown_response = true; break; } } else { switch (sptr_rx_packet->header.code) { case RADIUS_ACCOUNTING_RESPONSE: ++p_server->statistics.accounting_responses_rx; break; default: ++p_server->statistics.accounting_unknown_type_packets_rx; server_unknown_response = true; break; } }#ifdef __RADIUS_MIB__ semGive (g_sem_radius_mib);#endif if (server_unknown_response == true) { buffer_free (sptr_rx_packet); rw_container_free_iterator (request_entry_iterator); return; } if (radius.disable_verify_response_authenticator != TRUE) { if (verify_radius_response_authenticator (sptr_rx_packet, (BYTE *)p_request_entry->packet_header.authenticator, p_server) == FAIL) {#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif switch (sptr_rx_packet->header.code) { case RADIUS_ACCESS_ACCEPT: case RADIUS_ACCESS_REJECT: case RADIUS_ACCESS_CHALLENGE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -