X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmain%2Flisten.c;h=b6e2b4dbcd237b62f8b0630455123853aa0b9ab4;hb=1147ab4f2843e6deee5fd07f2b716de7cbb1675b;hp=2b8a9735c7e64a3e7944ef46b3bd31822e0df708;hpb=b22c5b92aeae768a8c410e18efe9843bc5028e89;p=freeradius.git diff --git a/src/main/listen.c b/src/main/listen.c index 2b8a973..b6e2b4d 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -201,7 +201,8 @@ RADCLIENT *client_listener_find(const rad_listen_t *listener, * can be defined. */ rad_assert(client->dynamic == 0); - } else { + + } else if (!client->dynamic && client->rate_limit) { /* * The IP is unknown, so we've found an enclosing * network. Enable DoS protection. We only @@ -293,7 +294,7 @@ static int rad_status_server(REQUEST *request) case RAD_LISTEN_NONE: #endif case RAD_LISTEN_AUTH: - dval = dict_valbyname(PW_AUTZ_TYPE, "Status-Server"); + dval = dict_valbyname(PW_AUTZ_TYPE, 0, "Status-Server"); if (dval) { rcode = module_authorize(dval->value, request); } else { @@ -320,7 +321,7 @@ static int rad_status_server(REQUEST *request) #ifdef WITH_ACCOUNTING case RAD_LISTEN_ACCT: - dval = dict_valbyname(PW_ACCT_TYPE, "Status-Server"); + dval = dict_valbyname(PW_ACCT_TYPE, 0, "Status-Server"); if (dval) { rcode = module_accounting(dval->value, request); } else { @@ -347,7 +348,7 @@ static int rad_status_server(REQUEST *request) * the WG. We like it, so it goes in here. */ case RAD_LISTEN_COA: - dval = dict_valbyname(PW_RECV_COA_TYPE, "Status-Server"); + dval = dict_valbyname(PW_RECV_COA_TYPE, 0, "Status-Server"); if (dval) { rcode = module_recv_coa(dval->value, request); } else { @@ -619,7 +620,7 @@ static int auth_tcp_accept(rad_listen_t *listener, /* * This function is stupid and complicated. */ -static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize) +static int socket_print(const rad_listen_t *this, char *buffer, size_t bufsize) { size_t len; listen_socket_t *sock = this->data; @@ -724,6 +725,7 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize) return 1; } +#ifdef WITH_PROXY /* * Maybe it's a socket that we opened to a home server. */ @@ -754,7 +756,8 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize) return 1; } -#endif +#endif /* WITH_PROXY */ +#endif /* WITH_TCP */ ADDSTRING(" address "); @@ -781,6 +784,8 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize) return 1; } +extern int check_config; /* radiusd.c */ + /* * Parse an authentication or accounting socket. @@ -865,18 +870,33 @@ static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) * TCP requires a destination IP for sockets. * UDP doesn't, so it's allowed. */ +#ifdef WITH_PROXY if ((this->type == RAD_LISTEN_PROXY) && (sock->proto != IPPROTO_UDP)) { cf_log_err(cf_sectiontoitem(cs), "Proxy listeners can only listen on proto = udp"); return -1; } -#endif +#endif /* WITH_PROXY */ +#endif /* WITH_TCP */ } sock->my_ipaddr = ipaddr; sock->my_port = listen_port; + if (check_config) { + if (home_server_find(&sock->my_ipaddr, sock->my_port, sock->proto)) { + char buffer[128]; + + DEBUG("ERROR: We have been asked to listen on %s port %d, which is also listed as a home server. This can create a proxy loop.", + ip_ntoh(&sock->my_ipaddr, buffer, sizeof(buffer)), + sock->my_port); + return -1; + } + + return 0; /* don't do anything */ + } + /* * If we can bind to interfaces, do so, * else don't. @@ -1329,9 +1349,9 @@ static int rad_coa_reply(REQUEST *request) /* * Inform the user about RFC requirements. */ - s1 = pairfind(request->proxy->vps, PW_STATE); + s1 = pairfind(request->proxy->vps, PW_STATE, 0); if (s1) { - s2 = pairfind(request->proxy_reply->vps, PW_STATE); + s2 = pairfind(request->proxy_reply->vps, PW_STATE, 0); if (!s2) { DEBUG("WARNING: Client was sent State in CoA, and did not respond with State."); @@ -1385,10 +1405,10 @@ static int rad_coa_recv(REQUEST *request) * with Service-Type = Authorize-Only, it MUST * have a State attribute in it. */ - vp = pairfind(request->packet->vps, PW_SERVICE_TYPE); + vp = pairfind(request->packet->vps, PW_SERVICE_TYPE, 0); if (request->packet->code == PW_COA_REQUEST) { if (vp && (vp->vp_integer == 17)) { - vp = pairfind(request->packet->vps, PW_STATE); + vp = pairfind(request->packet->vps, PW_STATE, 0); if (!vp || (vp->length == 0)) { RDEBUG("ERROR: CoA-Request with Service-Type = Authorize-Only MUST contain a State attribute"); request->reply->code = PW_COA_NAK; @@ -1436,7 +1456,7 @@ static int rad_coa_recv(REQUEST *request) * Copy State from the request to the reply. * See RFC 5176 Section 3.3. */ - vp = paircopy2(request->packet->vps, PW_STATE); + vp = paircopy2(request->packet->vps, PW_STATE, 0); if (vp) pairadd(&request->reply->vps, vp); /* @@ -1816,7 +1836,7 @@ static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = { #ifdef WITH_COMMAND_SOCKET /* TCP command socket */ - { command_socket_parse, NULL, + { command_socket_parse, command_socket_free, command_domain_accept, command_domain_send, command_socket_print, command_socket_encode, command_socket_decode }, #endif @@ -1905,15 +1925,15 @@ static int listen_bind(rad_listen_t *this) case RAD_LISTEN_COA: svp = getservbyname ("radius-dynauth", "udp"); if (svp != NULL) { - sock->port = ntohs(svp->s_port); + sock->my_port = ntohs(svp->s_port); } else { - sock->port = PW_COA_UDP_PORT; + sock->my_port = PW_COA_UDP_PORT; } break; #endif default: - radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind."); + DEBUG("WARNING: Internal sanity check failed in binding to socket. Ignoring problem."); return -1; } } @@ -1958,10 +1978,10 @@ static int listen_bind(rad_listen_t *this) * been defined, set the scope to the scope of * the interface. */ - if (sock->ipaddr.af == AF_INET6) { - if (sock->ipaddr.scope == 0) { - sock->ipaddr.scope = if_nametoindex(sock->interface); - if (sock->ipaddr.scope == 0) { + if (sock->my_ipaddr.af == AF_INET6) { + if (sock->my_ipaddr.scope == 0) { + sock->my_ipaddr.scope = if_nametoindex(sock->interface); + if (sock->my_ipaddr.scope == 0) { close(this->fd); radlog(L_ERR, "Failed finding interface %s: %s", sock->interface, strerror(errno)); @@ -2425,6 +2445,28 @@ static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server) return this; } +#ifdef WITH_PROXY +static int is_loopback(const fr_ipaddr_t *ipaddr) +{ + /* + * We shouldn't proxy on loopback. + */ + if ((ipaddr->af == AF_INET) && + (ipaddr->ipaddr.ip4addr.s_addr == htonl(INADDR_LOOPBACK))) { + return 1; + } + +#ifdef HAVE_STRUCT_SOCKADDR_IN6 + if ((ipaddr->af == AF_INET6) && + (IN6_IS_ADDR_LINKLOCAL(&ipaddr->ipaddr.ip6addr))) { + return 1; + } +#endif + + return 0; +} +#endif + /* * Generate a list of listeners. Takes an input list of * listeners, too, so we don't close sockets with waiting packets. @@ -2651,6 +2693,15 @@ int listen_init(CONF_SECTION *config, rad_listen_t **head) add_sockets: /* + * No sockets to receive packets, this is an error. + * proxying is pointless. + */ + if (!*head) { + radlog(L_ERR, "The server is not configured to listen on any ports. Cannot start."); + return -1; + } + + /* * Print out which sockets we're listening on, and * add them to the event list. */ @@ -2690,6 +2741,9 @@ add_sockets: for (this = *head; this != NULL; this = this->next) { if (this->type == RAD_LISTEN_AUTH) { sock = this->data; + + if (is_loopback(&sock->my_ipaddr)) continue; + if (home.src_ipaddr.af == AF_UNSPEC) { home.src_ipaddr = sock->my_ipaddr; } @@ -2699,6 +2753,9 @@ add_sockets: #ifdef WITH_ACCT if (this->type == RAD_LISTEN_ACCT) { sock = this->data; + + if (is_loopback(&sock->my_ipaddr)) continue; + if (home.src_ipaddr.af == AF_UNSPEC) { home.src_ipaddr = sock->my_ipaddr; } @@ -2758,12 +2815,12 @@ void listen_free(rad_listen_t **head) } #ifdef WITH_TCP - if ((this->type == RAD_LISTEN_AUTH) || + if ((this->type == RAD_LISTEN_AUTH) #ifdef WITH_ACCT - (this->type == RAD_LISTEN_ACCT) || + || (this->type == RAD_LISTEN_ACCT) #endif #ifdef WITH_PROXY - (this->type == RAD_LISTEN_PROXY) + || (this->type == RAD_LISTEN_PROXY) #endif ) { listen_socket_t *sock = this->data; @@ -2789,8 +2846,11 @@ RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr, for (this = mainconfig.listen; this != NULL; this = this->next) { listen_socket_t *sock; - if ((this->type != RAD_LISTEN_AUTH) && - (this->type != RAD_LISTEN_ACCT)) continue; + if ((this->type != RAD_LISTEN_AUTH) +#ifdef WITH_ACCOUNTING + && (this->type != RAD_LISTEN_ACCT) +#endif + ) continue; sock = this->data; @@ -2815,8 +2875,11 @@ rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port) * FIXME: For TCP, ignore the *secondary* * listeners associated with the main socket. */ - if ((this->type != RAD_LISTEN_AUTH) && - (this->type != RAD_LISTEN_ACCT)) continue; + if ((this->type != RAD_LISTEN_AUTH) +#ifdef WITH_ACCOUNTING + && (this->type != RAD_LISTEN_ACCT) +#endif + ) continue; sock = this->data; @@ -2826,18 +2889,9 @@ rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port) } if ((sock->my_port == port) && - ((sock->my_ipaddr.af == AF_INET) && - (sock->my_ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY))) { + fr_inaddr_any(&sock->my_ipaddr)) { return this; } - -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - if ((sock->my_port == port) && - (sock->my_ipaddr.af == AF_INET6) && - (IN6_IS_ADDR_UNSPECIFIED(&sock->my_ipaddr.ipaddr.ip6addr))) { - return this; - } -#endif } return NULL;