⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radius_server.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		sess->last_reply = reply;		sess->last_from_port = from_port;		sess->last_identifier = msg->hdr->identifier;		os_memcpy(sess->last_authenticator, msg->hdr->authenticator,			  16);	} else {		data->counters.packets_dropped++;		client->counters.packets_dropped++;	}	if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) {		RADIUS_DEBUG("Removing completed session 0x%x after timeout",			     sess->sess_id);		eloop_cancel_timeout(radius_server_session_remove_timeout,				     data, sess);		eloop_register_timeout(10, 0,				       radius_server_session_remove_timeout,				       data, sess);	}	return 0;}static void radius_server_receive_auth(int sock, void *eloop_ctx,				       void *sock_ctx){	struct radius_server_data *data = eloop_ctx;	u8 *buf = NULL;	struct sockaddr_storage from;	socklen_t fromlen;	int len;	struct radius_client *client = NULL;	struct radius_msg *msg = NULL;	char abuf[50];	int from_port = 0;	buf = os_malloc(RADIUS_MAX_MSG_LEN);	if (buf == NULL) {		goto fail;	}	fromlen = sizeof(from);	len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,		       (struct sockaddr *) &from, &fromlen);	if (len < 0) {		perror("recvfrom[radius_server]");		goto fail;	}#ifdef CONFIG_IPV6	if (data->ipv6) {		struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;		if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf))		    == NULL)			abuf[0] = '\0';		from_port = ntohs(from6->sin6_port);		RADIUS_DEBUG("Received %d bytes from %s:%d",			     len, abuf, from_port);		client = radius_server_get_client(data,						  (struct in_addr *)						  &from6->sin6_addr, 1);	}#endif /* CONFIG_IPV6 */	if (!data->ipv6) {		struct sockaddr_in *from4 = (struct sockaddr_in *) &from;		os_strlcpy(abuf, inet_ntoa(from4->sin_addr), sizeof(abuf));		from_port = ntohs(from4->sin_port);		RADIUS_DEBUG("Received %d bytes from %s:%d",			     len, abuf, from_port);		client = radius_server_get_client(data, &from4->sin_addr, 0);	}	RADIUS_DUMP("Received data", buf, len);	if (client == NULL) {		RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);		data->counters.invalid_requests++;		goto fail;	}	msg = radius_msg_parse(buf, len);	if (msg == NULL) {		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");		data->counters.malformed_access_requests++;		client->counters.malformed_access_requests++;		goto fail;	}	os_free(buf);	buf = NULL;	if (wpa_debug_level <= MSG_MSGDUMP) {		radius_msg_dump(msg);	}	if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {		RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);		data->counters.unknown_types++;		client->counters.unknown_types++;		goto fail;	}	data->counters.access_requests++;	client->counters.access_requests++;	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,				       client->shared_secret_len, NULL)) {		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);		data->counters.bad_authenticators++;		client->counters.bad_authenticators++;		goto fail;	}	if (radius_server_request(data, msg, (struct sockaddr *) &from,				  fromlen, client, abuf, from_port, NULL) ==	    -2)		return; /* msg was stored with the session */fail:	if (msg) {		radius_msg_free(msg);		os_free(msg);	}	os_free(buf);}static int radius_server_open_socket(int port){	int s;	struct sockaddr_in addr;	s = socket(PF_INET, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket");		return -1;	}	os_memset(&addr, 0, sizeof(addr));	addr.sin_family = AF_INET;	addr.sin_port = htons(port);	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		perror("bind");		close(s);		return -1;	}	return s;}#ifdef CONFIG_IPV6static int radius_server_open_socket6(int port){	int s;	struct sockaddr_in6 addr;	s = socket(PF_INET6, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket[IPv6]");		return -1;	}	os_memset(&addr, 0, sizeof(addr));	addr.sin6_family = AF_INET6;	os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));	addr.sin6_port = htons(port);	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		perror("bind");		close(s);		return -1;	}	return s;}#endif /* CONFIG_IPV6 */static void radius_server_free_sessions(struct radius_server_data *data,					struct radius_session *sessions){	struct radius_session *session, *prev;	session = sessions;	while (session) {		prev = session;		session = session->next;		radius_server_session_free(data, prev);	}}static void radius_server_free_clients(struct radius_server_data *data,				       struct radius_client *clients){	struct radius_client *client, *prev;	client = clients;	while (client) {		prev = client;		client = client->next;		radius_server_free_sessions(data, prev->sessions);		os_free(prev->shared_secret);		os_free(prev);	}}static struct radius_client *radius_server_read_clients(const char *client_file, int ipv6){	FILE *f;	const int buf_size = 1024;	char *buf, *pos;	struct radius_client *clients, *tail, *entry;	int line = 0, mask, failed = 0, i;	struct in_addr addr;#ifdef CONFIG_IPV6	struct in6_addr addr6;#endif /* CONFIG_IPV6 */	unsigned int val;	f = fopen(client_file, "r");	if (f == NULL) {		RADIUS_ERROR("Could not open client file '%s'", client_file);		return NULL;	}	buf = os_malloc(buf_size);	if (buf == NULL) {		fclose(f);		return NULL;	}	clients = tail = NULL;	while (fgets(buf, buf_size, f)) {		/* Configuration file format:		 * 192.168.1.0/24 secret		 * 192.168.1.2 secret		 * fe80::211:22ff:fe33:4455/64 secretipv6		 */		line++;		buf[buf_size - 1] = '\0';		pos = buf;		while (*pos != '\0' && *pos != '\n')			pos++;		if (*pos == '\n')			*pos = '\0';		if (*buf == '\0' || *buf == '#')			continue;		pos = buf;		while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||		       (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||		       (*pos >= 'A' && *pos <= 'F')) {			pos++;		}		if (*pos == '\0') {			failed = 1;			break;		}		if (*pos == '/') {			char *end;			*pos++ = '\0';			mask = strtol(pos, &end, 10);			if ((pos == end) ||			    (mask < 0 || mask > (ipv6 ? 128 : 32))) {				failed = 1;				break;			}			pos = end;		} else {			mask = ipv6 ? 128 : 32;			*pos++ = '\0';		}		if (!ipv6 && inet_aton(buf, &addr) == 0) {			failed = 1;			break;		}#ifdef CONFIG_IPV6		if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {			if (inet_pton(AF_INET, buf, &addr) <= 0) {				failed = 1;				break;			}			/* Convert IPv4 address to IPv6 */			if (mask <= 32)				mask += (128 - 32);			os_memset(addr6.s6_addr, 0, 10);			addr6.s6_addr[10] = 0xff;			addr6.s6_addr[11] = 0xff;			os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,				  4);		}#endif /* CONFIG_IPV6 */		while (*pos == ' ' || *pos == '\t') {			pos++;		}		if (*pos == '\0') {			failed = 1;			break;		}		entry = os_zalloc(sizeof(*entry));		if (entry == NULL) {			failed = 1;			break;		}		entry->shared_secret = os_strdup(pos);		if (entry->shared_secret == NULL) {			failed = 1;			os_free(entry);			break;		}		entry->shared_secret_len = os_strlen(entry->shared_secret);		entry->addr.s_addr = addr.s_addr;		if (!ipv6) {			val = 0;			for (i = 0; i < mask; i++)				val |= 1 << (31 - i);			entry->mask.s_addr = htonl(val);		}#ifdef CONFIG_IPV6		if (ipv6) {			int offset = mask / 8;			os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);			os_memset(entry->mask6.s6_addr, 0xff, offset);			val = 0;			for (i = 0; i < (mask % 8); i++)				val |= 1 << (7 - i);			if (offset < 16)				entry->mask6.s6_addr[offset] = val;		}#endif /* CONFIG_IPV6 */		if (tail == NULL) {			clients = tail = entry;		} else {			tail->next = entry;			tail = entry;		}	}	if (failed) {		RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);		radius_server_free_clients(NULL, clients);		clients = NULL;	}	os_free(buf);	fclose(f);	return clients;}struct radius_server_data *radius_server_init(struct radius_server_conf *conf){	struct radius_server_data *data;#ifndef CONFIG_IPV6	if (conf->ipv6) {		fprintf(stderr, "RADIUS server compiled without IPv6 "			"support.\n");		return NULL;	}#endif /* CONFIG_IPV6 */	data = os_zalloc(sizeof(*data));	if (data == NULL)		return NULL;	os_get_time(&data->start_time);	data->conf_ctx = conf->conf_ctx;	data->eap_sim_db_priv = conf->eap_sim_db_priv;	data->ssl_ctx = conf->ssl_ctx;	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 (conf->eap_fast_a_id)		data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);	data->get_eap_user = conf->get_eap_user;	data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;	data->tnc = conf->tnc;	data->clients = radius_server_read_clients(conf->client_file,						   conf->ipv6);	if (data->clients == NULL) {		printf("No RADIUS clients configured.\n");		radius_server_deinit(data);		return NULL;	}#ifdef CONFIG_IPV6	if (conf->ipv6)		data->auth_sock = radius_server_open_socket6(conf->auth_port);	else#endif /* CONFIG_IPV6 */	data->auth_sock = radius_server_open_socket(conf->auth_port);	if (data->auth_sock < 0) {		printf("Failed to open UDP socket for RADIUS authentication "		       "server\n");		radius_server_deinit(data);		return NULL;	}	if (eloop_register_read_sock(data->auth_sock,				     radius_server_receive_auth,				     data, NULL)) {		radius_server_deinit(data);		return NULL;	}	return data;}void radius_server_deinit(struct radius_server_data *data){	if (data == NULL)		return;	if (data->auth_sock >= 0) {		eloop_unregister_read_sock(data->auth_sock);		close(data->auth_sock);	}	radius_server_free_clients(data, data->clients);	os_free(data->pac_opaque_encr_key);	os_free(data->eap_fast_a_id);	os_free(data);}int radius_server_get_mib(struct radius_server_data *data, char *buf,			  size_t buflen){	int ret, uptime;	unsigned int idx;	char *end, *pos;	struct os_time now;	struct radius_client *cli;	/* RFC 2619 - RADIUS Authentication Server MIB */	if (data == NULL || buflen == 0)		return 0;	pos = buf;	end = buf + buflen;	os_get_time(&now);	uptime = (now.sec - data->start_time.sec) * 100 +		((now.usec - data->start_time.usec) / 10000) % 100;	ret = os_snprintf(pos, end - pos,			  "RADIUS-AUTH-SERVER-MIB\n"			  "radiusAuthServIdent=hostapd\n"			  "radiusAuthServUpTime=%d\n"			  "radiusAuthServResetTime=0\n"			  "radiusAuthServConfigReset=4\n",			  uptime);	if (ret < 0 || ret >= end - pos) {		*pos = '\0';		return pos - buf;	}	pos += ret;	ret = os_snprintf(pos, end - pos,			  "radiusAuthServTotalAccessRequests=%u\n"			  "radiusAuthServTotalInvalidRequests=%u\n"			  "radiusAuthServTotalDupAccessRequests=%u\n"			  "radiusAuthServTotalAccessAccepts=%u\n"			  "radiusAuthServTotalAccessRejects=%u\n"			  "radiusAuthServTotalAccessChallenges=%u\n"			  "radiusAuthServTotalMalformedAccessRequests=%u\n"			  "radiusAuthServTotalBadAuthenticators=%u\n"			  "radiusAuthServTotalPacketsDropped=%u\n"			  "radiusAuthServTotalUnknownTypes=%u\n",			  data->counters.access_requests,			  data->counters.invalid_requests,			  data->counters.dup_access_requests,			  data->counters.access_accepts,			  data->counters.access_rejects,			  data->counters.access_challenges,			  data->counters.malformed_access_requests,			  data->counters.bad_authenticators,			  data->counters.packets_dropped,			  data->counters.unknown_types);	if (ret < 0 || ret >= end - pos) {		*pos = '\0';		return pos - buf;	}	pos += ret;	for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {		char abuf[50], mbuf[50];#ifdef CONFIG_IPV6		if (data->ipv6) {			if (inet_ntop(AF_INET6, &cli->addr6, abuf,				      sizeof(abuf)) == NULL)				abuf[0] = '\0';			if (inet_ntop(AF_INET6, &cli->mask6, abuf,				      sizeof(mbuf)) == NULL)				mbuf[0] = '\0';		}#endif /* CONFIG_IPV6 */		if (!data->ipv6) {			os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));			os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));		}		ret = os_snprintf(pos, end - pos,				  "radiusAuthClientIndex=%u\n"				  "radiusAuthClientAddress=%s/%s\n"				  "radiusAuthServAccessRequests=%u\n"				  "radiusAuthServDupAccessRequests=%u\n"				  "radiusAuthServAccessAccepts=%u\n"				  "radiusAuthServAccessRejects=%u\n"				  "radiusAuthServAccessChallenges=%u\n"				  "radiusAuthServMalformedAccessRequests=%u\n"				  "radiusAuthServBadAuthenticators=%u\n"				  "radiusAuthServPacketsDropped=%u\n"				  "radiusAuthServUnknownTypes=%u\n",				  idx,				  abuf, mbuf,				  cli->counters.access_requests,				  cli->counters.dup_access_requests,				  cli->counters.access_accepts,				  cli->counters.access_rejects,				  cli->counters.access_challenges,				  cli->counters.malformed_access_requests,				  cli->counters.bad_authenticators,				  cli->counters.packets_dropped,				  cli->counters.unknown_types);		if (ret < 0 || ret >= end - pos) {			*pos = '\0';			return pos - buf;		}		pos += ret;	}	return pos - buf;}static int radius_server_get_eap_user(void *ctx, const u8 *identity,				      size_t identity_len, int phase2,				      struct eap_user *user){	struct radius_session *sess = ctx;	struct radius_server_data *data = sess->server;	return data->get_eap_user(data->conf_ctx, identity, identity_len,				  phase2, user);}static struct eapol_callbacks radius_server_eapol_cb ={	.get_eap_user = radius_server_get_eap_user,};void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx){	struct radius_client *cli;	struct radius_session *s, *sess = NULL;	struct radius_msg *msg;	if (data == NULL)		return;	for (cli = data->clients; cli; cli = cli->next) {		for (s = cli->sessions; s; s = s->next) {			if (s->eap == ctx && s->last_msg) {				sess = s;				break;			}			if (sess)				break;		}		if (sess)			break;	}	if (sess == NULL) {		RADIUS_DEBUG("No session matched callback ctx");		return;	}	msg = sess->last_msg;	sess->last_msg = NULL;	eap_sm_pending_cb(sess->eap);	if (radius_server_request(data, msg,				  (struct sockaddr *) &sess->last_from,				  sess->last_fromlen, cli,				  sess->last_from_addr,				  sess->last_from_port, sess) == -2)		return; /* msg was stored with the session */	radius_msg_free(msg);	os_free(msg);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -