From: Alan T. DeKok Date: Fri, 2 Apr 2021 16:32:50 +0000 (-0400) Subject: run policies to see if we can accept the RadSec connection X-Git-Tag: release_3_0_22~119 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d66b200234cada57deec321e6afcf1f2768d07b;p=thirdparty%2Ffreeradius-server.git run policies to see if we can accept the RadSec connection --- diff --git a/src/include/listen.h b/src/include/listen.h index 4f50bbf808..c5b45f0a7e 100644 --- a/src/include/listen.h +++ b/src/include/listen.h @@ -80,6 +80,7 @@ struct rad_listen { #ifdef WITH_TLS fr_tls_server_conf_t *tls; + bool check_client_connections; #endif rad_listen_recv_t recv; @@ -146,6 +147,12 @@ typedef struct listen_socket_t { pthread_mutex_t mutex; uint8_t *data; size_t partial; + enum { + LISTEN_TLS_INIT = 0, + LISTEN_TLS_CHECKING, + LISTEN_TLS_SETUP, + LISTEN_TLS_RUNNING, + } state; #endif RADCLIENT_LIST *clients; diff --git a/src/main/listen.c b/src/main/listen.c index 27ce67c6bc..5b9fd287d5 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -1068,6 +1068,10 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) } #endif + + rcode = cf_item_parse(cs, "check_client_connections", FR_ITEM_POINTER(PW_TYPE_BOOLEAN, &this->check_client_connections), "no"); + if (rcode < 0) return -1; + } #else /* WITH_TLS */ /* @@ -2114,6 +2118,14 @@ static int proxy_socket_tcp_recv(rad_listen_t *listener) static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request) { +#ifdef WITH_TLS + /* + * Don't encode fake packets. + */ + listen_socket_t *sock = listener->data; + if (sock->state == LISTEN_TLS_CHECKING) return 0; +#endif + if (!request->reply->code) return 0; if (rad_encode(request->reply, request->packet, request->client->secret) < 0) { diff --git a/src/main/tls_listen.c b/src/main/tls_listen.c index bedbd0cd67..d0e8530919 100644 --- a/src/main/tls_listen.c +++ b/src/main/tls_listen.c @@ -187,6 +187,17 @@ static int tls_socket_recv(rad_listen_t *listener) request = sock->request; + if (sock->state == LISTEN_TLS_SETUP) { + RDEBUG3("Setting connection state to RUNNING"); + sock->state = LISTEN_TLS_RUNNING; + + if (sock->ssn->clean_out.used < 20) { + goto get_application_data; + } + + goto read_application_data; + } + RDEBUG3("Reading from socket %d", request->packet->sockfd); PTHREAD_MUTEX_LOCK(&sock->mutex); @@ -198,7 +209,7 @@ static int tls_socket_recv(rad_listen_t *listener) if (SSL_pending(sock->ssn->ssl)) { RDEBUG3("Reading pending buffered data"); sock->ssn->dirty_in.used = 0; - goto get_application_data; + goto check_for_setup; } rcode = read(request->packet->sockfd, @@ -253,12 +264,42 @@ static int tls_socket_recv(rad_listen_t *listener) } /* - * FIXME: Run the request through a virtual - * server in order to see if we like the - * certificate presented by the client. + * Else we MUST be finished the SSL setup. */ } + /* + * Run the request through a virtual server in + * order to see if we like the certificate + * presented by the client. + */ +check_for_setup: + if (sock->state == LISTEN_TLS_INIT) { + rad_assert(SSL_is_init_finished(sock->ssn->ssl)); + sock->ssn->is_init_finished = true; + if (!listener->check_client_connections) { + sock->state = LISTEN_TLS_RUNNING; + goto get_application_data; + } + + RDEBUG("Checking initial connection"); + request->packet->vps = fr_pair_list_copy(request->packet, sock->certs); + rdebug_pair_list(L_DBG_LVL_1, request, request->packet->vps, "&request:"); + + /* + * Fake out a Status-Server packet, which + * does NOT have a Message-Authenticator, + * or any other contents. + */ + request->packet->code = PW_CODE_STATUS_SERVER; + request->packet->data = talloc_zero_array(packet, uint8_t, 20); + request->packet->data[0] = PW_CODE_STATUS_SERVER; + request->packet->data[3] = 20; + sock->state = LISTEN_TLS_CHECKING; + PTHREAD_MUTEX_UNLOCK(&sock->mutex); + return 1; + } + /* * Try to get application data. */ @@ -276,6 +317,16 @@ get_application_data: return 0; } + /* + * Hold application data if we're not yet in the RUNNING + * state. + */ + if (sock->state != LISTEN_TLS_RUNNING) { + RDEBUG3("Holding application data until setup is complete"); + return 0; + } + +read_application_data: /* * We now have a bunch of application data. */ @@ -360,6 +411,7 @@ redo: rad_assert(client != NULL); packet = talloc_steal(NULL, sock->packet); + sock->request->packet = NULL; sock->packet = NULL; /* @@ -407,7 +459,11 @@ redo: #endif case PW_CODE_STATUS_SERVER: - if (!main_config.status_server) { + if (!main_config.status_server +#ifdef WITH_TLS + && !listener->check_client_connections +#endif + ) { FR_STATS_INC(auth, total_unknown_types); WARN("Ignoring Status-Server request due to security configuration"); rad_free(&packet); @@ -470,6 +526,30 @@ int dual_tls_send(rad_listen_t *listener, REQUEST *request) if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; + /* + * See if the policies allowed this connection. + */ + if (sock->state == LISTEN_TLS_CHECKING) { + if (request->reply->code != PW_CODE_ACCESS_ACCEPT) { + REDEBUG("Rejecting client TLS connection"); + listener->status = RAD_LISTEN_STATUS_REMOVE_NOW; + listener->tls = NULL; /* parent owns this! */ + + /* + * Tell the event handler that an FD has disappeared. + */ + radius_update_listener(listener); + return 0; + } + + rad_assert(sock->request->packet != request->packet); + + RDEBUG("Accepting client TLS connection"); + sock->state = LISTEN_TLS_SETUP; + (void) dual_tls_recv(listener); + return 0; + } + /* * Accounting reject's are silently dropped. *