]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/radius/radius_server.c
Remove trailing whitespace
[thirdparty/hostap.git] / src / radius / radius_server.c
index 78c996146c81f14da6ddd0eb1f73aed48fdcef10..e8bef45fc255c4d2c4aa56f4e1b9aa6a646d189b 100644 (file)
  */
 #define RADIUS_SESSION_TIMEOUT 60
 
+/**
+ * RADIUS_SESSION_MAINTAIN - Completed session expiration timeout in seconds
+ */
+#define RADIUS_SESSION_MAINTAIN 5
+
 /**
  * RADIUS_MAX_SESSION - Maximum number of active sessions
  */
-#define RADIUS_MAX_SESSION 100
+#define RADIUS_MAX_SESSION 1000
 
 /**
  * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
  */
 #define RADIUS_MAX_MSG_LEN 3000
 
-static struct eapol_callbacks radius_server_eapol_cb;
+static const struct eapol_callbacks radius_server_eapol_cb;
 
 struct radius_client;
 struct radius_server_data;
@@ -251,6 +256,22 @@ struct radius_server_data {
         */
        const char *server_id;
 
+       /**
+        * erp - Whether EAP Re-authentication Protocol (ERP) is enabled
+        *
+        * This controls whether the authentication server derives ERP key
+        * hierarchy (rRK and rIK) from full EAP authentication and allows
+        * these keys to be used to perform ERP to derive rMSK instead of full
+        * EAP authentication to derive MSK.
+        */
+       int erp;
+
+       const char *erp_domain;
+
+       struct dl_list erp_keys; /* struct eap_server_erp_key */
+
+       unsigned int tls_session_lifetime;
+
        /**
         * wps - Wi-Fi Protected Setup context
         *
@@ -623,7 +644,7 @@ radius_server_get_new_session(struct radius_server_data *data,
 
        os_memset(&tmp, 0, sizeof(tmp));
        res = data->get_eap_user(data->conf_ctx, user, user_len, 0, &tmp);
-       os_free(tmp.password);
+       bin_clear_free(tmp.password, tmp.password_len);
 
        if (res != 0) {
                RADIUS_DEBUG("User-Name not found from user database");
@@ -639,12 +660,12 @@ radius_server_get_new_session(struct radius_server_data *data,
        sess->accept_attr = tmp.accept_attr;
        sess->macacl = tmp.macacl;
 
-       sess->username = os_malloc(user_len * 2 + 1);
+       sess->username = os_malloc(user_len * 4 + 1);
        if (sess->username == NULL) {
                radius_server_session_free(data, sess);
                return NULL;
        }
-       printf_encode(sess->username, user_len * 2 + 1, user, user_len);
+       printf_encode(sess->username, user_len * 4 + 1, user, user_len);
 
        sess->nas_ip = os_strdup(from_addr);
        if (sess->nas_ip == NULL) {
@@ -673,6 +694,8 @@ radius_server_get_new_session(struct radius_server_data *data,
        eap_conf.pwd_group = data->pwd_group;
        eap_conf.server_id = (const u8 *) data->server_id;
        eap_conf.server_id_len = os_strlen(data->server_id);
+       eap_conf.erp = data->erp;
+       eap_conf.tls_session_lifetime = data->tls_session_lifetime;
        radius_server_testing_options(sess, &eap_conf);
        sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
                                       &eap_conf);
@@ -852,7 +875,7 @@ radius_server_macacl(struct radius_server_data *data,
                                         os_strlen(sess->username), 0, &tmp);
                if (res || !tmp.macacl || tmp.password == NULL) {
                        RADIUS_DEBUG("No MAC ACL user entry");
-                       os_free(tmp.password);
+                       bin_clear_free(tmp.password, tmp.password_len);
                        code = RADIUS_CODE_ACCESS_REJECT;
                } else {
                        u8 buf[128];
@@ -861,10 +884,10 @@ radius_server_macacl(struct radius_server_data *data,
                                (u8 *) client->shared_secret,
                                client->shared_secret_len,
                                buf, sizeof(buf));
-                       os_free(tmp.password);
+                       bin_clear_free(tmp.password, tmp.password_len);
 
                        if (res < 0 || pw_len != (size_t) res ||
-                           os_memcmp(pw, buf, res) != 0) {
+                           os_memcmp_const(pw, buf, res) != 0) {
                                RADIUS_DEBUG("Incorrect User-Password");
                                code = RADIUS_CODE_ACCESS_REJECT;
                        }
@@ -1039,7 +1062,7 @@ static int radius_server_request(struct radius_server_data *data,
                             "message");
                return -1;
        }
-                     
+
        eap = radius_msg_get_eap(msg);
        if (eap == NULL && sess->macacl) {
                reply = radius_server_macacl(data, client, sess, msg);
@@ -1154,7 +1177,7 @@ send_reply:
                             sess->sess_id);
                eloop_cancel_timeout(radius_server_session_remove_timeout,
                                     data, sess);
-               eloop_register_timeout(10, 0,
+               eloop_register_timeout(RADIUS_SESSION_MAINTAIN, 0,
                                       radius_server_session_remove_timeout,
                                       data, sess);
        }
@@ -1687,6 +1710,7 @@ radius_server_init(struct radius_server_conf *conf)
        if (data == NULL)
                return NULL;
 
+       dl_list_init(&data->erp_keys);
        os_get_reltime(&data->start_time);
        data->conf_ctx = conf->conf_ctx;
        data->eap_sim_db_priv = conf->eap_sim_db_priv;
@@ -1695,8 +1719,10 @@ radius_server_init(struct radius_server_conf *conf)
        data->ipv6 = conf->ipv6;
        if (conf->pac_opaque_encr_key) {
                data->pac_opaque_encr_key = os_malloc(16);
-               os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
-                         16);
+               if (data->pac_opaque_encr_key) {
+                       os_memcpy(data->pac_opaque_encr_key,
+                                 conf->pac_opaque_encr_key, 16);
+               }
        }
        if (conf->eap_fast_a_id) {
                data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
@@ -1725,6 +1751,9 @@ radius_server_init(struct radius_server_conf *conf)
                        data->eap_req_id_text_len = conf->eap_req_id_text_len;
                }
        }
+       data->erp = conf->erp;
+       data->erp_domain = conf->erp_domain;
+       data->tls_session_lifetime = conf->tls_session_lifetime;
 
        if (conf->subscr_remediation_url) {
                data->subscr_remediation_url =
@@ -1801,6 +1830,24 @@ radius_server_init(struct radius_server_conf *conf)
 }
 
 
+/**
+ * radius_server_erp_flush - Flush all ERP keys
+ * @data: RADIUS server context from radius_server_init()
+ */
+void radius_server_erp_flush(struct radius_server_data *data)
+{
+       struct eap_server_erp_key *erp;
+
+       if (data == NULL)
+               return;
+       while ((erp = dl_list_first(&data->erp_keys, struct eap_server_erp_key,
+                                   list)) != NULL) {
+               dl_list_del(&erp->list);
+               bin_clear_free(erp, sizeof(*erp));
+       }
+}
+
+
 /**
  * radius_server_deinit - Deinitialize RADIUS server
  * @data: RADIUS server context from radius_server_init()
@@ -1836,6 +1883,8 @@ void radius_server_deinit(struct radius_server_data *data)
                sqlite3_close(data->db);
 #endif /* CONFIG_SQLITE */
 
+       radius_server_erp_flush(data);
+
        os_free(data);
 }
 
@@ -1874,7 +1923,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
                          "radiusAuthServResetTime=0\n"
                          "radiusAuthServConfigReset=4\n",
                          uptime);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                *pos = '\0';
                return pos - buf;
        }
@@ -1913,7 +1962,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
                          data->counters.malformed_acct_requests,
                          data->counters.acct_bad_authenticators,
                          data->counters.unknown_acct_types);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                *pos = '\0';
                return pos - buf;
        }
@@ -1926,7 +1975,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
                        if (inet_ntop(AF_INET6, &cli->addr6, abuf,
                                      sizeof(abuf)) == NULL)
                                abuf[0] = '\0';
-                       if (inet_ntop(AF_INET6, &cli->mask6, abuf,
+                       if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
                                      sizeof(mbuf)) == NULL)
                                mbuf[0] = '\0';
                }
@@ -1971,7 +2020,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
                                  cli->counters.malformed_acct_requests,
                                  cli->counters.acct_bad_authenticators,
                                  cli->counters.unknown_acct_types);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        *pos = '\0';
                        return pos - buf;
                }
@@ -1997,6 +2046,12 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
                sess->remediation = user->remediation;
                sess->macacl = user->macacl;
        }
+
+       if (ret) {
+               RADIUS_DEBUG("%s: User-Name not found from user database",
+                            __func__);
+       }
+
        return ret;
 }
 
@@ -2017,11 +2072,57 @@ static void radius_server_log_msg(void *ctx, const char *msg)
 }
 
 
-static struct eapol_callbacks radius_server_eapol_cb =
+#ifdef CONFIG_ERP
+
+static const char * radius_server_get_erp_domain(void *ctx)
+{
+       struct radius_session *sess = ctx;
+       struct radius_server_data *data = sess->server;
+
+       return data->erp_domain;
+}
+
+
+static struct eap_server_erp_key *
+radius_server_erp_get_key(void *ctx, const char *keyname)
+{
+       struct radius_session *sess = ctx;
+       struct radius_server_data *data = sess->server;
+       struct eap_server_erp_key *erp;
+
+       dl_list_for_each(erp, &data->erp_keys, struct eap_server_erp_key,
+                        list) {
+               if (os_strcmp(erp->keyname_nai, keyname) == 0)
+                       return erp;
+       }
+
+       return NULL;
+}
+
+
+static int radius_server_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
+{
+       struct radius_session *sess = ctx;
+       struct radius_server_data *data = sess->server;
+
+       dl_list_add(&data->erp_keys, &erp->list);
+       return 0;
+}
+
+#endif /* CONFIG_ERP */
+
+
+static const struct eapol_callbacks radius_server_eapol_cb =
 {
        .get_eap_user = radius_server_get_eap_user,
        .get_eap_req_id_text = radius_server_get_eap_req_id_text,
        .log_msg = radius_server_log_msg,
+#ifdef CONFIG_ERP
+       .get_erp_send_reauth_start = NULL,
+       .get_erp_domain = radius_server_get_erp_domain,
+       .erp_get_key = radius_server_erp_get_key,
+       .erp_add_key = radius_server_erp_add_key,
+#endif /* CONFIG_ERP */
 };
 
 
@@ -2048,8 +2149,6 @@ void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
                                sess = s;
                                break;
                        }
-                       if (sess)
-                               break;
                }
                if (sess)
                        break;