From 0174889e3a03ce0336980c8c9bb63759a2f5457f Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Wed, 24 Sep 2008 14:05:54 +0200 Subject: [PATCH] Move "unknown" client code to common area This simplifies the code (less is better), and enables us to add a central DoS method. From a quick inspection of the code, there appears to be more that can be done. Many of the receive functions have duplicate code, which should be abstracted. --- src/include/radiusd.h | 2 +- src/main/dhcpd.c | 9 +--- src/main/listen.c | 122 +++++++++++++++++++++----------------------------- src/main/vmps.c | 9 +--- 4 files changed, 55 insertions(+), 87 deletions(-) diff --git a/src/include/radiusd.h b/src/include/radiusd.h index 8329b7b..bf126ba 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -596,7 +596,7 @@ void listen_free(rad_listen_t **head); int listen_init(CONF_SECTION *cs, rad_listen_t **head); rad_listen_t *proxy_new_listener(void); RADCLIENT *client_listener_find(const rad_listen_t *listener, - const fr_ipaddr_t *ipaddr); + const fr_ipaddr_t *ipaddr, int src_port); #ifdef WITH_STATS RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr, int port); diff --git a/src/main/dhcpd.c b/src/main/dhcpd.c index 8d78b2c..8b38569 100644 --- a/src/main/dhcpd.c +++ b/src/main/dhcpd.c @@ -126,13 +126,8 @@ static int dhcp_socket_recv(rad_listen_t *listener, } if ((client = client_listener_find(listener, - &packet->src_ipaddr)) == NULL) { - char buffer[256]; - radlog(L_ERR, "Ignoring request from unknown client %s port %d", - inet_ntop(packet->src_ipaddr.af, - &packet->src_ipaddr.ipaddr, - buffer, sizeof(buffer)), - packet->src_port); + &packet->src_ipaddr, + packet->src_port)) == NULL) { rad_free(&packet); return 0; } diff --git a/src/main/listen.c b/src/main/listen.c index 7e7d504..1e07e4f 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -80,15 +80,16 @@ static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type); * Find a per-socket client. */ RADCLIENT *client_listener_find(const rad_listen_t *listener, - const fr_ipaddr_t *ipaddr) + const fr_ipaddr_t *ipaddr, int src_port) { #ifdef WITH_DYNAMIC_CLIENTS int rcode; - time_t now; listen_socket_t *sock; REQUEST *request; - RADCLIENT *client, *created; + RADCLIENT *created; #endif + time_t now; + RADCLIENT *client; RADCLIENT_LIST *clients; rad_assert(listener != NULL); @@ -116,9 +117,39 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, */ rad_assert(clients != NULL); -#ifdef WITH_DYNAMIC_CLIENTS client = client_find(clients, ipaddr); - if (!client) return NULL; + if (!client) { + static time_t last_printed = 0; + char name[256], buffer[128]; + +#ifdef WITH_DYNAMIC_CLIENTS + unknown: /* used only for dynamic clients */ +#endif + + /* + * DoS attack quenching, but only in debug mode. + * If they're running in debug mode, show them + * every packet. + */ + if (debug_flag == 0) { + now = time(NULL); + if (last_printed == now) return NULL; + + last_printed = now; + } + + listener->print(listener, name, sizeof(name)); + + radlog(L_ERR, "Ignoring request to %s from unknown client %s port %d", + name, inet_ntop(ipaddr->af, &ipaddr->ipaddr, + buffer, sizeof(buffer)), + src_port); + return NULL; + } + +#ifndef WITH_DYNAMIC_CLIENTS + return client; /* return the found client. */ +#else /* * No server defined, and it's not dynamic. Return it. @@ -162,8 +193,8 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, /* * WTF? */ - if (!client) return NULL; - if (!client->client_server) return NULL; + if (!client) goto unknown; + if (!client->client_server) goto unknown; /* * At this point, 'client' is the enclosing @@ -178,25 +209,25 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, * allow one new client per second. Known * clients aren't subject to this restriction. */ - if (now == client->last_new_client) return NULL; + if (now == client->last_new_client) goto unknown; } client->last_new_client = now; request = request_alloc(); - if (!request) return NULL; + if (!request) goto unknown; request->listener = listener; request->client = client; request->packet = rad_alloc(0); if (!request->packet) { request_free(&request); - return NULL; + goto unknown; } request->reply = rad_alloc(0); if (!request->reply) { request_free(&request); - return NULL; + goto unknown; } request->packet->timestamp = request->timestamp; request->number = 0; @@ -237,7 +268,7 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, if (rcode != RLM_MODULE_OK) { request_free(&request); - return NULL; + goto unknown; } /* @@ -252,15 +283,13 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, /* * This frees the client if it isn't valid. */ - if (!client_validate(clients, client, created)) { - return NULL; - } + if (!client_validate(clients, client, created)) goto unknown; } request_free(&request); - return created; /* may be NULL */ -#else - return client_find(clients, ipaddr); + if (!created) goto unknown; + + return created; #endif } @@ -652,7 +681,6 @@ static int stats_socket_recv(rad_listen_t *listener, ssize_t rcode; int code, src_port; RADIUS_PACKET *packet; - char buffer[128]; RADCLIENT *client; fr_ipaddr_t src_ipaddr; @@ -667,25 +695,9 @@ static int stats_socket_recv(rad_listen_t *listener, } if ((client = client_listener_find(listener, - &src_ipaddr)) == NULL) { + &src_ipaddr, src_port)) == NULL) { rad_recv_discard(listener->fd); RAD_STATS_TYPE_INC(listener, total_invalid_requests); - - if (debug_flag > 0) { - char name[1024]; - - listener->print(listener, name, sizeof(name)); - - /* - * This is debugging rather than logging, so that - * DoS attacks don't affect us. - */ - DEBUG("Ignoring request to %s from unknown client %s port %d", - name, - inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr, - buffer, sizeof(buffer)), src_port); - } - return 0; } @@ -738,7 +750,6 @@ static int auth_socket_recv(rad_listen_t *listener, int code, src_port; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; - char buffer[128]; RADCLIENT *client; fr_ipaddr_t src_ipaddr; @@ -753,25 +764,9 @@ static int auth_socket_recv(rad_listen_t *listener, } if ((client = client_listener_find(listener, - &src_ipaddr)) == NULL) { + &src_ipaddr, src_port)) == NULL) { rad_recv_discard(listener->fd); RAD_STATS_TYPE_INC(listener, total_invalid_requests); - - if (debug_flag > 0) { - char name[1024]; - - listener->print(listener, name, sizeof(name)); - - /* - * This is debugging rather than logging, so that - * DoS attacks don't affect us. - */ - DEBUG("Ignoring request to %s from unknown client %s port %d", - name, - inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr, - buffer, sizeof(buffer)), src_port); - } - return 0; } @@ -840,7 +835,6 @@ static int acct_socket_recv(rad_listen_t *listener, int code, src_port; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; - char buffer[128]; RADCLIENT *client; fr_ipaddr_t src_ipaddr; @@ -855,25 +849,9 @@ static int acct_socket_recv(rad_listen_t *listener, } if ((client = client_listener_find(listener, - &src_ipaddr)) == NULL) { + &src_ipaddr, src_port)) == NULL) { rad_recv_discard(listener->fd); RAD_STATS_TYPE_INC(listener, total_invalid_requests); - - /* - * This is debugging rather than logging, so that - * DoS attacks don't affect us. - */ - if (debug_flag > 0) { - char name[1024]; - - listener->print(listener, name, sizeof(name)); - - DEBUG("Ignoring request to %s from unknown client %s port %d", - name, - inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr, - buffer, sizeof(buffer)), src_port); - } - return 0; } diff --git a/src/main/vmps.c b/src/main/vmps.c index f968e98..b88b11a 100644 --- a/src/main/vmps.c +++ b/src/main/vmps.c @@ -42,7 +42,6 @@ int vqp_socket_recv(rad_listen_t *listener, { RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; - char buffer[128]; RADCLIENT *client; packet = vqp_recv(listener->fd); @@ -52,12 +51,8 @@ int vqp_socket_recv(rad_listen_t *listener, } if ((client = client_listener_find(listener, - &packet->src_ipaddr)) == NULL) { - radlog(L_ERR, "Ignoring request from unknown client %s port %d", - inet_ntop(packet->src_ipaddr.af, - &packet->src_ipaddr.ipaddr, - buffer, sizeof(buffer)), - packet->src_port); + &packet->src_ipaddr, + packet->src_port)) == NULL) { rad_free(&packet); return 0; } -- 2.1.4