]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add WITH_COA_TUNNEL definition
authorAlan T. DeKok <aland@freeradius.org>
Wed, 31 Mar 2021 13:52:41 +0000 (09:52 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 2 Apr 2021 19:12:23 +0000 (15:12 -0400)
along with recv_coa functionality in the home server definition.
and parse / verify the home server configuration for recv coa

src/include/features-h
src/include/realms.h
src/main/realms.c

index f24a52d20edb8165067acdc09b58aa9265848567..ce28e9c51978aa5fa6963b81646ab36fb66ea18b 100644 (file)
 #      endif
 #    endif
 #  endif
+
+#  ifdef WITH_COA
+#    ifndef WITHOUT_COA_TUNNEL
+#      define WITH_COA_TUNNEL (1)
+#    endif
+#  endif
+#endif
+
+#ifdef WITH_COA_TUNNEL
+#  ifdef WITHOUT_TLS
+#    error Reverse CoA requests requires TLS
+#  endif
 #endif
index dcb420371e5f1927792a2ea1108097bbc109a1eb..be4998ec08619b0a0662f7d2c760446383f95a33 100644 (file)
@@ -21,10 +21,15 @@ typedef enum {
        HOME_TYPE_INVALID = 0,
        HOME_TYPE_AUTH,         //!< Authentication server
        HOME_TYPE_ACCT,         //!< Accounting server
-       HOME_TYPE_AUTH_ACCT     //!< Authentication and accounting server
+       HOME_TYPE_AUTH_ACCT,    //!< Authentication and accounting server
 
 #ifdef WITH_COA
-       ,HOME_TYPE_COA          //!< CoA destination (NAS or Proxy)
+       HOME_TYPE_COA,          //!< CoA destination (NAS or Proxy)
+
+#ifdef WITH_COA_TUNNEL
+       HOME_TYPE_AUTH_COA,     //!< auth + coa
+       HOME_TYPE_AUTH_ACCT_COA, //!< auth + acct + coa
+#endif
 #endif
 } home_type_t;
 
@@ -60,6 +65,9 @@ typedef struct home_server {
 
        bool                    dual;                   //!< One of a pair of homeservers on consecutive ports.
        bool                    dynamic;                //!< is this a dynamically added home server?
+#ifdef WITH_COA_TUNNEL
+       bool                    recv_coa;               //!< receive CoA packets, too
+#endif
        char const              *server;                //!< For internal proxying
        char const              *parent_server;
 
@@ -120,6 +128,9 @@ typedef struct home_server {
        uint32_t                coa_mrc;
        uint32_t                coa_mrt;
        uint32_t                coa_mrd;
+#ifdef WITH_COA_TUNNEL
+       char const              *coa_server;            //!< for accepting incoming CoA requests
+#endif
 #endif
 #ifdef WITH_TLS
        fr_tls_server_conf_t    *tls;
index 682c58f35114d73588f9eeb06533eb2ecc83ecf4..a8a88669a1cbfa8f5e30e2120a0115d057433058 100644 (file)
@@ -73,6 +73,10 @@ static const FR_NAME_NUMBER home_server_types[] = {
        { "acct",               HOME_TYPE_ACCT },
        { "auth+acct",          HOME_TYPE_AUTH_ACCT },
        { "coa",                HOME_TYPE_COA },
+#ifdef WITH_COA_TUNNEL
+       { "auth+coa",           HOME_TYPE_AUTH_COA },
+       { "auth+acct+coa",      HOME_TYPE_AUTH_ACCT_COA },
+#endif
        { NULL, 0 }
 };
 
@@ -429,6 +433,16 @@ static CONF_PARSER home_server_coa[] = {
        { "mrd",  FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, coa_mrd), STRINGIFY(30) },
        CONF_PARSER_TERMINATOR
 };
+
+
+
+#ifdef WITH_COA_TUNNEL
+static CONF_PARSER home_server_recv_coa[] = {
+       { "virtual_server",  FR_CONF_OFFSET(PW_TYPE_STRING, home_server_t, coa_server), NULL },
+       CONF_PARSER_TERMINATOR
+};
+#endif
+
 #endif
 
 static CONF_PARSER home_server_config[] = {
@@ -478,6 +492,9 @@ static CONF_PARSER home_server_config[] = {
 
 #ifdef WITH_COA
        { "coa", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) home_server_coa },
+#ifdef WITH_COA_TUNNEL
+       { "recv_coa", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) home_server_recv_coa },
+#endif
 #endif
 
        CONF_PARSER_TERMINATOR
@@ -677,6 +694,20 @@ bool realm_home_server_add(home_server_t *home)
                }
        }
 
+#ifdef WITH_COA_TUNNEL
+       if (home->recv_coa) {
+               if (!home->tls) {
+                       ERROR("TLS is required in order to accept CoA requests from a home server");
+                       return false;
+               }
+
+               if (!home->coa_server) {
+                       ERROR("A 'virtual_server' configuration is required in order to accept CoA requests from a home server");
+                       return false;
+               }
+       }
+#endif
+
        /*
         *      Mark it as already processed
         */
@@ -741,7 +772,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
                }
 
                /*
-                *      Try and find a 'server' section off the root of
+                *      Try and find a "server" section off the root of
                 *      the config with a name that matches the
                 *      virtual_server.
                 */
@@ -789,6 +820,17 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
                                goto error;
                        }
                        break;
+
+#ifdef WITH_COA_TUNNEL
+               case HOME_TYPE_AUTH_ACCT_COA:
+                       home->dual = true;
+                       home->recv_coa = true;
+                       break;
+
+               case HOME_TYPE_AUTH_COA:
+                       home->recv_coa = true;
+                       break;
+#endif
 #endif
 
                case HOME_TYPE_INVALID:
@@ -815,6 +857,10 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
                        }
 
                        if (((home->type == HOME_TYPE_AUTH) ||
+#ifdef WITH_COA_TUNNEL
+                            (home->type == HOME_TYPE_AUTH_COA) ||
+                            (home->type == HOME_TYPE_AUTH_ACCT_COA) ||
+#endif
                             (home->type == HOME_TYPE_AUTH_ACCT)) && !home->ping_user_password) {
                                cf_log_err_cs(cs, "You must supply a 'password' to enable status_check=request");
                                goto error;
@@ -879,6 +925,38 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
        }
 #endif
 
+       /*
+        *      Check the reverse CoA configuration.
+        */
+#ifdef WITH_COA_TUNNEL
+       if (home->recv_coa) {
+               if (!tls) {
+                       ERROR("TLS is required in order to accept CoA requests from a home server");
+                       goto error;
+               }
+
+               if (!home->coa_server) {
+                       ERROR("A 'virtual_server' configuration is required in order to accept CoA requests from a home server");
+                       goto error;
+               }
+
+               /*
+                *      Try and find a 'server' section off the root of
+                *      the config with a name that matches the coa
+                *      virtual_server.
+                */
+               if (!rc) {
+                       ERROR("Dynamic home servers cannot accept CoA requests");
+                       goto error;
+               }
+
+               if (!cf_section_sub_find_name2(rc->cs, "server", home->coa_server)) {
+                       cf_log_err_cs(cs, "No such coa server %s", home->coa_server);
+                       goto error;
+               }
+       }
+#endif
+
        /*
         *      If were doing RADSEC (tls+tcp) the secret should default
         *      to radsec, else a secret must be set.
@@ -1123,6 +1201,16 @@ static int pool_check_home_server(UNUSED realm_config_t *rc, CONF_PAIR *cp,
        case HOME_TYPE_ACCT:
                myhome.type = HOME_TYPE_AUTH_ACCT;
                home = rbtree_finddata(home_servers_byname, &myhome);
+#ifdef WITH_COA_TUNNEL
+               if (!home) {
+                       myhome.type = HOME_TYPE_AUTH_COA;
+                       home = rbtree_finddata(home_servers_byname, &myhome);
+                       if(!home) {
+                               myhome.type = HOME_TYPE_AUTH_ACCT_COA;
+                               home = rbtree_finddata(home_servers_byname, &myhome);
+                       }
+               }
+#endif
                if (home) {
                        *phome = home;
                        return 1;
@@ -1414,6 +1502,16 @@ static int server_pool_add(realm_config_t *rc,
                        case HOME_TYPE_ACCT:
                                myhome.type = HOME_TYPE_AUTH_ACCT;
                                home = rbtree_finddata(home_servers_byname, &myhome);
+#ifdef WITH_COA_TUNNEL
+                               if (!home) {
+                                       myhome.type = HOME_TYPE_AUTH_COA;
+                                       home = rbtree_finddata(home_servers_byname, &myhome);
+                                       if (!home) {
+                                               myhome.type = HOME_TYPE_AUTH_ACCT_COA;
+                                               home = rbtree_finddata(home_servers_byname, &myhome);
+                                       }
+                               }
+#endif
                                break;
 
                        default:
@@ -2983,6 +3081,14 @@ int home_server_afrom_file(char const *filename)
                goto error;
        }
 
+#ifdef COA_TUNNEL
+       if (home->recv_coa) {
+               fr_strerror_printf("Dynamic home_server '%s' cannot receive CoA requests'", p);
+               talloc_free(home);
+               goto error;
+       }
+#endif
+
        if (!realm_home_server_add(home)) {
                fr_strerror_printf("Failed adding home_server to the internal data structures");
                talloc_free(home);