Exemplo n.º 1
0
int radius_client_send(struct radius_client_data *radius,
		       struct radius_msg *msg, RadiusType msg_type,
		       const u8 *addr)
{
	struct hostapd_radius_servers *conf = radius->conf;
	u8 *shared_secret;
	size_t shared_secret_len;
	char *name;
	int s, res;

	if (msg_type == RADIUS_ACCT_INTERIM) {
		/* Remove any pending interim acct update for the same STA. */
		radius_client_list_del(radius, msg_type, addr);
	}

	if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
		if (conf->acct_server == NULL) {
			hostapd_logger(radius->ctx, NULL,
				       HOSTAPD_MODULE_RADIUS,
				       HOSTAPD_LEVEL_INFO,
				       "No accounting server configured");
			return -1;
		}
		shared_secret = conf->acct_server->shared_secret;
		shared_secret_len = conf->acct_server->shared_secret_len;
		radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
		name = "accounting";
		s = radius->acct_sock;
		conf->acct_server->requests++;
	} else {
		if (conf->auth_server == NULL) {
			hostapd_logger(radius->ctx, NULL,
				       HOSTAPD_MODULE_RADIUS,
				       HOSTAPD_LEVEL_INFO,
				       "No authentication server configured");
			return -1;
		}
		shared_secret = conf->auth_server->shared_secret;
		shared_secret_len = conf->auth_server->shared_secret_len;
		radius_msg_finish(msg, shared_secret, shared_secret_len);
		name = "authentication";
		s = radius->auth_sock;
		conf->auth_server->requests++;
	}

	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
		       HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
		       "server", name);
	if (conf->msg_dumps)
		radius_msg_dump(msg);

	res = send(s, msg->buf, msg->buf_used, 0);
	if (res < 0)
		radius_client_handle_send_error(radius, s, msg_type);

	radius_client_list_add(radius, msg, msg_type, shared_secret,
			       shared_secret_len, addr);

	return res;
}
Exemplo n.º 2
0
static int radius_client_retransmit(struct radius_client_data *radius,
                                    struct radius_msg_list *entry,
                                    os_time_t now)
{
    struct hostapd_radius_servers *conf = radius->conf;
    int s;
    struct wpabuf *buf;

    if (entry->msg_type == RADIUS_ACCT ||
            entry->msg_type == RADIUS_ACCT_INTERIM) {
        s = radius->acct_sock;
        if (entry->attempts == 0)
            conf->acct_server->requests++;
        else {
            conf->acct_server->timeouts++;
            conf->acct_server->retransmissions++;
        }
    } else {
        s = radius->auth_sock;
        if (entry->attempts == 0)
            conf->auth_server->requests++;
        else {
            conf->auth_server->timeouts++;
            conf->auth_server->retransmissions++;
        }
    }

    /* retransmit; remove entry if too many attempts */
    entry->attempts++;
    hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
                   HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
                   radius_msg_get_hdr(entry->msg)->identifier);

    os_get_time(&entry->last_attempt);
    buf = radius_msg_get_buf(entry->msg);
    if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0)
        radius_client_handle_send_error(radius, s, entry->msg_type);

    entry->next_try = now + entry->next_wait;
    entry->next_wait *= 2;
    if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
        entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
    if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
        printf("Removing un-ACKed RADIUS message due to too many "
               "failed retransmit attempts\n");
        return 1;
    }

    return 0;
}
Exemplo n.º 3
0
static int radius_client_retransmit(struct radius_client_data *radius,
                                    struct radius_msg_list *entry, time_t now)
{
    struct hostapd_data *hapd = radius->hapd;
    int s;

    if (entry->msg_type == RADIUS_ACCT ||
            entry->msg_type == RADIUS_ACCT_INTERIM) {
        s = radius->acct_serv_sock;
        if (entry->attempts == 0)
            hapd->conf->acct_server->requests++;
        else {
            hapd->conf->acct_server->timeouts++;
            hapd->conf->acct_server->retransmissions++;
        }
    } else {
        s = radius->auth_serv_sock;
        if (entry->attempts == 0)
            hapd->conf->auth_server->requests++;
        else {
            hapd->conf->auth_server->timeouts++;
            hapd->conf->auth_server->retransmissions++;
        }
    }

    /* retransmit; remove entry if too many attempts */
    entry->attempts++;
    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
                  "\n", entry->msg->hdr->identifier);

    gettimeofday(&entry->last_attempt, NULL);
    if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
        radius_client_handle_send_error(radius, s, entry->msg_type);

    entry->next_try = now + entry->next_wait;
    entry->next_wait *= 2;
    if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
        entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
    if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
        printf("Removing un-ACKed RADIUS message due to too many "
               "failed retransmit attempts\n");
        return 1;
    }

    return 0;
}
Exemplo n.º 4
0
int radius_client_send(struct radius_client_data *radius,
                       struct radius_msg *msg, RadiusType msg_type, u8 *addr)
{
    struct hostapd_data *hapd = radius->hapd;
    u8 *shared_secret;
    size_t shared_secret_len;
    char *name;
    int s, res;

    if (msg_type == RADIUS_ACCT_INTERIM) {
        /* Remove any pending interim acct update for the same STA. */
        radius_client_list_del(radius, msg_type, addr);
    }

    if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
        shared_secret = hapd->conf->acct_server->shared_secret;
        shared_secret_len = hapd->conf->acct_server->shared_secret_len;
        radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
        name = "accounting";
        s = radius->acct_serv_sock;
        hapd->conf->acct_server->requests++;
    } else {
        shared_secret = hapd->conf->auth_server->shared_secret;
        shared_secret_len = hapd->conf->auth_server->shared_secret_len;
        radius_msg_finish(msg, shared_secret, shared_secret_len);
        name = "authentication";
        s = radius->auth_serv_sock;
        hapd->conf->auth_server->requests++;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "Sending RADIUS message to %s server\n", name);
    if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
        radius_msg_dump(msg);

    res = send(s, msg->buf, msg->buf_used, 0);
    if (res < 0)
        radius_client_handle_send_error(radius, s, msg_type);

    radius_client_list_add(radius, msg, msg_type, shared_secret,
                           shared_secret_len, addr);

    return res;
}
Exemplo n.º 5
0
/**
 * radius_client_send - Send a RADIUS request
 * @radius: RADIUS client context from radius_client_init()
 * @msg: RADIUS message to be sent
 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
 * @addr: MAC address of the device related to this message or %NULL
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
 * between accounting and interim accounting messages is that the interim
 * message will not be retransmitted. Instead, a callback is used to indicate
 * that the transmission failed for the specific station @addr so that a new
 * interim accounting update message can be generated with up-to-date session
 * data instead of trying to resend old information.
 *
 * The message is added on the retransmission queue and will be retransmitted
 * automatically until a response is received or maximum number of retries
 * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with
 * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue
 * automatically on transmission failure.
 *
 * The related device MAC address can be used to identify pending messages that
 * can be removed with radius_client_flush_auth().
 */
int radius_client_send(struct radius_client_data *radius,
		       struct radius_msg *msg, RadiusType msg_type,
		       const u8 *addr)
{
	struct hostapd_radius_servers *conf = radius->conf;
	const u8 *shared_secret;
	size_t shared_secret_len;
	char *name;
	int s, res;
	struct wpabuf *buf;

	if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
		if (conf->acct_server && radius->acct_sock < 0)
			radius_client_init_acct(radius);

		if (conf->acct_server == NULL || radius->acct_sock < 0 ||
		    conf->acct_server->shared_secret == NULL) {
			hostapd_logger(radius->ctx, NULL,
				       HOSTAPD_MODULE_RADIUS,
				       HOSTAPD_LEVEL_INFO,
				       "No accounting server configured");
			return -1;
		}
		shared_secret = conf->acct_server->shared_secret;
		shared_secret_len = conf->acct_server->shared_secret_len;
		radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
		name = "accounting";
		s = radius->acct_sock;
		conf->acct_server->requests++;
	} else {
		if (conf->auth_server && radius->auth_sock < 0)
			radius_client_init_auth(radius);

		if (conf->auth_server == NULL || radius->auth_sock < 0 ||
		    conf->auth_server->shared_secret == NULL) {
			hostapd_logger(radius->ctx, NULL,
				       HOSTAPD_MODULE_RADIUS,
				       HOSTAPD_LEVEL_INFO,
				       "No authentication server configured");
			return -1;
		}
		shared_secret = conf->auth_server->shared_secret;
		shared_secret_len = conf->auth_server->shared_secret_len;
		radius_msg_finish(msg, shared_secret, shared_secret_len);
		name = "authentication";
		s = radius->auth_sock;
		conf->auth_server->requests++;
	}

	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
		       HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
		       "server", name);
	if (conf->msg_dumps)
		radius_msg_dump(msg);

	buf = radius_msg_get_buf(msg);
	res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
	if (res < 0)
		radius_client_handle_send_error(radius, s, msg_type);

	radius_client_list_add(radius, msg, msg_type, shared_secret,
			       shared_secret_len, addr);

	return 0;
}
Exemplo n.º 6
0
static int radius_client_retransmit(struct radius_client_data *radius,
				    struct radius_msg_list *entry,
				    os_time_t now)
{
	struct hostapd_radius_servers *conf = radius->conf;
	int s;
	struct wpabuf *buf;
	size_t prev_num_msgs;
	u8 *acct_delay_time;
	size_t acct_delay_time_len;

	if (entry->msg_type == RADIUS_ACCT ||
	    entry->msg_type == RADIUS_ACCT_INTERIM) {
		if (radius->acct_sock < 0)
			radius_client_init_acct(radius);
		if (radius->acct_sock < 0 && conf->num_acct_servers > 1) {
			prev_num_msgs = radius->num_msgs;
			radius_client_acct_failover(radius);
			if (prev_num_msgs != radius->num_msgs)
				return 0;
		}
		s = radius->acct_sock;
		if (entry->attempts == 0)
			conf->acct_server->requests++;
		else {
			conf->acct_server->timeouts++;
			conf->acct_server->retransmissions++;
		}
	} else {
		if (radius->auth_sock < 0)
			radius_client_init_auth(radius);
		if (radius->auth_sock < 0 && conf->num_auth_servers > 1) {
			prev_num_msgs = radius->num_msgs;
			radius_client_auth_failover(radius);
			if (prev_num_msgs != radius->num_msgs)
				return 0;
		}
		s = radius->auth_sock;
		if (entry->attempts == 0)
			conf->auth_server->requests++;
		else {
			conf->auth_server->timeouts++;
			conf->auth_server->retransmissions++;
		}
	}

	if (entry->msg_type == RADIUS_ACCT_INTERIM) {
		wpa_printf(MSG_DEBUG,
			   "RADIUS: Failed to transmit interim accounting update to "
			   MACSTR " - drop message and request a new update",
			   MAC2STR(entry->addr));
		if (radius->interim_error_cb)
			radius->interim_error_cb(entry->addr,
						 radius->interim_error_cb_ctx);
		return 1;
	}

	if (s < 0) {
		wpa_printf(MSG_INFO,
			   "RADIUS: No valid socket for retransmission");
		return 1;
	}

	if (entry->msg_type == RADIUS_ACCT &&
	    radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
				    &acct_delay_time, &acct_delay_time_len,
				    NULL) == 0 &&
	    acct_delay_time_len == 4) {
		struct radius_hdr *hdr;
		u32 delay_time;

		/*
		 * Need to assign a new identifier since attribute contents
		 * changes.
		 */
		hdr = radius_msg_get_hdr(entry->msg);
		hdr->identifier = radius_client_get_id(radius);

		/* Update Acct-Delay-Time to show wait time in queue */
		delay_time = now - entry->first_try;
		WPA_PUT_BE32(acct_delay_time, delay_time);

		wpa_printf(MSG_DEBUG,
			   "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
			   delay_time);
		radius_msg_finish_acct(entry->msg, entry->shared_secret,
				       entry->shared_secret_len);
		if (radius->conf->msg_dumps)
			radius_msg_dump(entry->msg);
	}

	/* retransmit; remove entry if too many attempts */
	entry->attempts++;
	hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
		       HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
		       radius_msg_get_hdr(entry->msg)->identifier);

	os_get_reltime(&entry->last_attempt);
	buf = radius_msg_get_buf(entry->msg);
	if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
		if (radius_client_handle_send_error(radius, s, entry->msg_type)
		    > 0)
			return 0;
	}

	entry->next_try = now + entry->next_wait;
	entry->next_wait *= 2;
	if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
		entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
	if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
		wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
		return 1;
	}

	return 0;
}
Exemplo n.º 7
0
static int radius_client_retransmit(struct radius_client_data *radius,
				    struct radius_msg_list *entry,
				    os_time_t now)
{
	struct hostapd_radius_servers *conf = radius->conf;
	int s;
	struct wpabuf *buf;
	size_t prev_num_msgs;

	if (entry->msg_type == RADIUS_ACCT ||
	    entry->msg_type == RADIUS_ACCT_INTERIM) {
		if (radius->acct_sock < 0)
			radius_client_init_acct(radius);
		if (radius->acct_sock < 0 && conf->num_acct_servers > 1) {
			prev_num_msgs = radius->num_msgs;
			radius_client_acct_failover(radius);
			if (prev_num_msgs != radius->num_msgs)
				return 0;
		}
		s = radius->acct_sock;
		if (entry->attempts == 0)
			conf->acct_server->requests++;
		else {
			conf->acct_server->timeouts++;
			conf->acct_server->retransmissions++;
		}
	} else {
		if (radius->auth_sock < 0)
			radius_client_init_auth(radius);
		if (radius->auth_sock < 0 && conf->num_auth_servers > 1) {
			prev_num_msgs = radius->num_msgs;
			radius_client_auth_failover(radius);
			if (prev_num_msgs != radius->num_msgs)
				return 0;
		}
		s = radius->auth_sock;
		if (entry->attempts == 0)
			conf->auth_server->requests++;
		else {
			conf->auth_server->timeouts++;
			conf->auth_server->retransmissions++;
		}
	}
	if (s < 0) {
		wpa_printf(MSG_INFO,
			   "RADIUS: No valid socket for retransmission");
		return 1;
	}

	/* retransmit; remove entry if too many attempts */
	entry->attempts++;
	hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
		       HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
		       radius_msg_get_hdr(entry->msg)->identifier);

	os_get_reltime(&entry->last_attempt);
	buf = radius_msg_get_buf(entry->msg);
	if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
		if (radius_client_handle_send_error(radius, s, entry->msg_type)
		    > 0)
			return 0;
	}

	entry->next_try = now + entry->next_wait;
	entry->next_wait *= 2;
	if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
		entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
	if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
		wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
		return 1;
	}

	return 0;
}