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

📄 radius_server.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		    == 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;		snprintf(abuf, sizeof(abuf), "%s", inet_ntoa(from4->sin_addr));		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);		goto fail;	}	msg = radius_msg_parse(buf, len);	if (msg == NULL) {		RADIUS_DEBUG("Parsing incoming RADIUS frame failed");		goto fail;	}	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);		goto fail;	}	if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,				       client->shared_secret_len, NULL)) {		RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);		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);		free(msg);	}	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;	}	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;	}	memset(&addr, 0, sizeof(addr));	addr.sin6_family = AF_INET6;	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);		free(prev->shared_secret);		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 = 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);			memset(addr6.s6_addr, 0, 10);			addr6.s6_addr[10] = 0xff;			addr6.s6_addr[11] = 0xff;			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 = wpa_zalloc(sizeof(*entry));		if (entry == NULL) {			failed = 1;			break;		}		entry->shared_secret = strdup(pos);		if (entry->shared_secret == NULL) {			failed = 1;			free(entry);			break;		}		entry->shared_secret_len = 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;			memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);			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;	}	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 = wpa_zalloc(sizeof(*data));	if (data == NULL)		return NULL;	data->hostapd_conf = conf->hostapd_conf;	data->eap_sim_db_priv = conf->eap_sim_db_priv;	data->ssl_ctx = conf->ssl_ctx;	data->ipv6 = conf->ipv6;	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);	free(data);}int radius_server_get_mib(struct radius_server_data *data, char *buf,			  size_t buflen){	/* TODO: add support for RADIUS authentication server MIB */	return 0;}static Boolean radius_server_get_bool(void *ctx, enum eapol_bool_var variable){	struct radius_session *sess = ctx;	if (sess == NULL)		return FALSE;	switch (variable) {	case EAPOL_eapSuccess:		return sess->eapSuccess;	case EAPOL_eapRestart:		return sess->eapRestart;	case EAPOL_eapFail:		return sess->eapFail;	case EAPOL_eapResp:		return sess->eapResp;	case EAPOL_eapReq:		return sess->eapReq;	case EAPOL_eapNoReq:		return sess->eapNoReq;	case EAPOL_portEnabled:		return sess->portEnabled;	case EAPOL_eapTimeout:		return sess->eapTimeout;	}	return FALSE;}static void radius_server_set_bool(void *ctx, enum eapol_bool_var variable,			      Boolean value){	struct radius_session *sess = ctx;	if (sess == NULL)		return;	switch (variable) {	case EAPOL_eapSuccess:		sess->eapSuccess = value;		break;	case EAPOL_eapRestart:		sess->eapRestart = value;		break;	case EAPOL_eapFail:		sess->eapFail = value;		break;	case EAPOL_eapResp:		sess->eapResp = value;		break;	case EAPOL_eapReq:		sess->eapReq = value;		break;	case EAPOL_eapNoReq:		sess->eapNoReq = value;		break;	case EAPOL_portEnabled:		sess->portEnabled = value;		break;	case EAPOL_eapTimeout:		sess->eapTimeout = value;		break;	}}static void radius_server_set_eapReqData(void *ctx, const u8 *eapReqData,				    size_t eapReqDataLen){	struct radius_session *sess = ctx;	if (sess == NULL)		return;	free(sess->eapReqData);	sess->eapReqData = malloc(eapReqDataLen);	if (sess->eapReqData) {		memcpy(sess->eapReqData, eapReqData, eapReqDataLen);		sess->eapReqDataLen = eapReqDataLen;	} else {		sess->eapReqDataLen = 0;	}}static void radius_server_set_eapKeyData(void *ctx, const u8 *eapKeyData,				    size_t eapKeyDataLen){	struct radius_session *sess = ctx;	if (sess == NULL)		return;	free(sess->eapKeyData);	if (eapKeyData) {		sess->eapKeyData = malloc(eapKeyDataLen);		if (sess->eapKeyData) {			memcpy(sess->eapKeyData, eapKeyData, eapKeyDataLen);			sess->eapKeyDataLen = eapKeyDataLen;		} else {			sess->eapKeyDataLen = 0;		}	} else {		sess->eapKeyData = NULL;		sess->eapKeyDataLen = 0;	}}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;	const struct hostapd_eap_user *eap_user;	int i, count;	eap_user = hostapd_get_eap_user(sess->server->hostapd_conf, identity,					identity_len, phase2);	if (eap_user == NULL)		return -1;	memset(user, 0, sizeof(*user));	count = EAP_USER_MAX_METHODS;	if (count > EAP_MAX_METHODS)		count = EAP_MAX_METHODS;	for (i = 0; i < count; i++) {		user->methods[i].vendor = eap_user->methods[i].vendor;		user->methods[i].method = eap_user->methods[i].method;	}	if (eap_user->password) {		user->password = malloc(eap_user->password_len);		if (user->password == NULL)			return -1;		memcpy(user->password, eap_user->password,		       eap_user->password_len);		user->password_len = eap_user->password_len;		user->password_hash = eap_user->password_hash;	}	user->force_version = eap_user->force_version;	return 0;}static struct eapol_callbacks radius_server_eapol_cb ={	.get_bool = radius_server_get_bool,	.set_bool = radius_server_set_bool,	.set_eapReqData = radius_server_set_eapReqData,	.set_eapKeyData = radius_server_set_eapKeyData,	.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);	free(msg);}

⌨️ 快捷键说明

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