Ejemplo n.º 1
0
/**
 * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
 * @config: Configuration data (e.g., file name)
 * @get_complete_cb: Callback function for reporting availability of triplets
 * @ctx: Context pointer for get_complete_cb
 * Returns: Pointer to a private data structure or %NULL on failure
 */
void * eap_sim_db_init(const char *config,
		       void (*get_complete_cb)(void *ctx, void *session_ctx),
		       void *ctx)
{
	struct eap_sim_db_data *data;

	data = wpa_zalloc(sizeof(*data));
	if (data == NULL)
		return NULL;

	data->sock = -1;
	data->get_complete_cb = get_complete_cb;
	data->ctx = ctx;
	data->fname = VM_STRDUP(config);
	if (data->fname == NULL)
		goto fail;

	if (strncmp(data->fname, "unix:", 5) == 0) {
		if (eap_sim_db_open_socket(data))
			goto fail;
	}

	return data;

fail:
	eap_sim_db_close_socket(data);
	VM_FREE(data->fname);
	VM_FREE(data);
	return NULL;
}
Ejemplo n.º 2
0
/**
 * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface
 * @priv: Private data pointer from eap_sim_db_init()
 */
void eap_sim_db_deinit(void *priv)
{
	struct eap_sim_db_data *data = priv;
	struct eap_sim_pseudonym *p, *prev;
	struct eap_sim_reauth *r, *prevr;
	struct eap_sim_db_pending *pending, *prev_pending;

	eap_sim_db_close_socket(data);
	VM_FREE(data->fname);

	p = data->pseudonyms;
	while (p) {
		prev = p;
		p = p->next;
		eap_sim_db_free_pseudonym(prev);
	}

	r = data->reauths;
	while (r) {
		prevr = r;
		r = r->next;
		eap_sim_db_free_reauth(prevr);
	}

	pending = data->pending;
	while (pending) {
		prev_pending = pending;
		pending = pending->next;
		VM_FREE(prev_pending);
	}

	VM_FREE(data);
}
Ejemplo n.º 3
0
static struct radius_session *
radius_server_get_new_session(struct radius_server_data *data,
			      struct radius_client *client,
			      struct radius_msg *msg)
{
	u8 *user;
	size_t user_len;
	const struct hostapd_eap_user *eap_user;
	int res;
	struct radius_session *sess;
	struct eap_config eap_conf;

	RADIUS_DEBUG("Creating a new session");

	user = VM_MALLOC(256);
	if (user == NULL) {
		return NULL;
	}
	res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
	if (res < 0 || res > 256) {
		RADIUS_DEBUG("Could not get User-Name");
		VM_FREE(user);
		return NULL;
	}
	user_len = res;
	RADIUS_DUMP_ASCII("User-Name", user, user_len);

	eap_user = hostapd_get_eap_user(data->hostapd_conf, user, user_len, 0);
	VM_FREE(user);

	if (eap_user) {
		RADIUS_DEBUG("Matching user entry found");
		sess = radius_server_new_session(data, client);
		if (sess == NULL) {
			RADIUS_DEBUG("Failed to create a new session");
			return NULL;
		}
	} else {
		RADIUS_DEBUG("User-Name not found from user database");
		return NULL;
	}

	memset(&eap_conf, 0, sizeof(eap_conf));
	eap_conf.ssl_ctx = data->ssl_ctx;
	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
	eap_conf.backend_auth = TRUE;
	sess->eap = eap_sm_init(sess, &radius_server_eapol_cb, &eap_conf);
	if (sess->eap == NULL) {
		RADIUS_DEBUG("Failed to initialize EAP state machine for the "
			     "new session");
		radius_server_session_free(data, sess);
		return NULL;
	}
	sess->eapRestart = TRUE;
	sess->portEnabled = TRUE;

	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);

	return sess;
}
Ejemplo n.º 4
0
static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
{
	if (entry == NULL)
		return;
	VM_FREE(entry->identity);
	ieee802_1x_free_radius_class(&entry->radius_class);
	VM_FREE(entry);
}
Ejemplo n.º 5
0
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);
		VM_FREE(prev->shared_secret);
		VM_FREE(prev);
	}
}
Ejemplo n.º 6
0
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
			      size_t num_hw_features)
{
	size_t i;

	if (hw_features == NULL)
		return;

	for (i = 0; i < num_hw_features; i++) {
		VM_FREE(hw_features[i].channels);
		VM_FREE(hw_features[i].rates);
	}

	VM_FREE(hw_features);
}
Ejemplo n.º 7
0
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
			       struct eapol_state_machine *eapol)
{
	if (entry == NULL || eapol == NULL)
		return;

	if (entry->identity) {
		VM_FREE(eapol->identity);
		eapol->identity = VM_MALLOC(entry->identity_len);
		if (eapol->identity) {
			eapol->identity_len = entry->identity_len;
			memcpy(eapol->identity, entry->identity,
			       entry->identity_len);
		}
		wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA",
				  eapol->identity, eapol->identity_len);
	}

	ieee802_1x_free_radius_class(&eapol->radius_class);
	ieee802_1x_copy_radius_class(&eapol->radius_class,
				     &entry->radius_class);
	if (eapol->radius_class.attr) {
		wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
			   "PMKSA", (unsigned long) eapol->radius_class.count);
	}

	eapol->eap_type_authsrv = entry->eap_type_authsrv;
	eapol->sta->vlan_id = entry->vlan_id;
}
Ejemplo n.º 8
0
/*!	frees the given memory to heap
	\param buffer - address to free
*/
int FreeToHeap(void * free_buffer)
{
	HEAP_DATA_PTR heap_data_ptr;
	heap_data_ptr = STRUCT_ADDRESS_FROM_MEMBER( free_buffer, HEAP_DATA, buffer[0]);
	if ( heap_data_ptr->bucket_index == VM_BUCKET )
		VM_FREE( heap_data_ptr, (UINT32)heap_data_ptr->buffer[0]  );
	return FreeBuffer(heap_data_ptr, &CACHE_FROM_INDEX(heap_data_ptr->bucket_index) );
}
Ejemplo n.º 9
0
static int radius_server_reject(struct radius_server_data *data,
				struct radius_client *client,
				struct radius_msg *request,
				struct sockaddr *from, socklen_t fromlen,
				const char *from_addr, int from_port)
{
	struct radius_msg *msg;
	int ret = 0;
	struct eap_hdr eapfail;

	RADIUS_DEBUG("Reject invalid request from %s:%d",
		     from_addr, from_port);

	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
			     request->hdr->identifier);
	if (msg == NULL) {
		return -1;
	}

	memset(&eapfail, 0, sizeof(eapfail));
	eapfail.code = EAP_CODE_FAILURE;
	eapfail.identifier = 0;
	eapfail.length = htons(sizeof(eapfail));

	if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
		RADIUS_DEBUG("Failed to add EAP-Message attribute");
	}

	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
		radius_msg_free(msg);
		os_free(msg);
		return -1;
	}

	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
				  client->shared_secret_len,
				  request->hdr->authenticator) < 0) {
		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
	}

	if (wpa_debug_level <= MSG_MSGDUMP) {
		radius_msg_dump(msg);
	}

	data->counters.access_rejects++;
	client->counters.access_rejects++;
	if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
		   (struct sockaddr *) from, sizeof(*from)) < 0) {
		perror("sendto[RADIUS SRV]");
		ret = -1;
	}

	radius_msg_free(msg);
	VM_FREE(msg);

	return ret;
}
Ejemplo n.º 10
0
/**
 * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
 * @priv: Private data pointer from eap_sim_db_init()
 * @identity: Identity of the user (may be permanent identity or pseudonym)
 * @identity_len: Length of identity
 * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
 * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
 * free it.
 * @mk: 16-byte MK from the previous full authentication
 * Returns: 0 on success, -1 on failure
 *
 * This function adds a new re-authentication entry for an EAP-SIM user.
 * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
 * anymore.
 */
int eap_sim_db_add_reauth(void *priv, const u8 *identity,
			  size_t identity_len, char *reauth_id, u16 counter,
			  const u8 *mk)
{
	struct eap_sim_db_data *data = priv;
	struct eap_sim_reauth *r;
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add reauth_id for identity",
			  identity, identity_len);
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: reauth_id: %s", reauth_id);

	r = eap_sim_db_get_reauth(data, identity, identity_len);
	if (r == NULL)
		r = eap_sim_db_get_reauth_id(data, identity, identity_len);

	if (r) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
			   "reauth_id: %s", r->reauth_id);
		VM_FREE(r->reauth_id);
		r->reauth_id = reauth_id;
	} else {
		r = wpa_zalloc(sizeof(*r));
		if (r == NULL) {
			VM_FREE(reauth_id);
			return -1;
		}

		r->next = data->reauths;
		r->identity = VM_MALLOC(identity_len);
		if (r->identity == NULL) {
			VM_FREE(r);
			VM_FREE(reauth_id);
			return -1;
		}
		memcpy(r->identity, identity, identity_len);
		r->identity_len = identity_len;
		r->reauth_id = reauth_id;
		data->reauths = r;
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry");
	}

	r->counter = counter;
	memcpy(r->mk, mk, EAP_SIM_MK_LEN);

	return 0;
}
Ejemplo n.º 11
0
/**
 * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym
 * @priv: Private data pointer from eap_sim_db_init()
 * @identity: Identity of the user (may be permanent identity or pseudonym)
 * @identity_len: Length of identity
 * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer,
 * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not
 * free it.
 * Returns: 0 on success, -1 on failure
 *
 * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is
 * responsible of freeing pseudonym buffer once it is not needed anymore.
 */
int eap_sim_db_add_pseudonym(void *priv, const u8 *identity,
			     size_t identity_len, char *pseudonym)
{
	struct eap_sim_db_data *data = priv;
	struct eap_sim_pseudonym *p;
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add pseudonym for identity",
			  identity, identity_len);
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pseudonym: %s", pseudonym);

	/* TODO: could store last two pseudonyms */
	p = eap_sim_db_get_pseudonym(data, identity, identity_len);
	if (p == NULL)
		p = eap_sim_db_get_pseudonym_id(data, identity, identity_len);

	if (p) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
			   "pseudonym: %s", p->pseudonym);
		VM_FREE(p->pseudonym);
		p->pseudonym = pseudonym;
		return 0;
	}

	p = wpa_zalloc(sizeof(*p));
	if (p == NULL) {
		VM_FREE(pseudonym);
		return -1;
	}

	p->next = data->pseudonyms;
	p->identity = VM_MALLOC(identity_len);
	if (p->identity == NULL) {
		VM_FREE(p);
		VM_FREE(pseudonym);
		return -1;
	}
	memcpy(p->identity, identity, identity_len);
	p->identity_len = identity_len;
	p->pseudonym = pseudonym;
	data->pseudonyms = p;

	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry");
	return 0;
}
Ejemplo n.º 12
0
static void eap_sim_db_close_socket(struct eap_sim_db_data *data)
{
	if (data->sock >= 0) {
		eloop_unregister_read_sock(data->sock);
		close(data->sock);
		data->sock = -1;
	}
	if (data->local_sock) {
		unlink(data->local_sock);
		VM_FREE(data->local_sock);
		data->local_sock = NULL;
	}
}
Ejemplo n.º 13
0
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);

	VM_FREE(data);
}
Ejemplo n.º 14
0
static void radius_server_set_eapReqData(void *ctx, const u8 *eapReqData,
				    size_t eapReqDataLen)
{
	struct radius_session *sess = ctx;
	if (sess == NULL)
		return;

	VM_FREE(sess->eapReqData);
	sess->eapReqData = VM_MALLOC(eapReqDataLen);
	if (sess->eapReqData) {
		memcpy(sess->eapReqData, eapReqData, eapReqDataLen);
		sess->eapReqDataLen = eapReqDataLen;
	} else {
		sess->eapReqDataLen = 0;
	}
}
Ejemplo n.º 15
0
/**
 * pmksa_cache_deinit - Free all entries in PMKSA cache
 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
 */
void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
{
	struct rsn_pmksa_cache_entry *entry, *prev;
	int i;

	if (pmksa == NULL)
		return;

	entry = pmksa->pmksa;
	while (entry) {
		prev = entry;
		entry = entry->next;
		_pmksa_cache_free_entry(prev);
	}
	eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
	for (i = 0; i < PMKID_HASH_SIZE; i++)
		pmksa->pmkid[i] = NULL;
	VM_FREE(pmksa);
}
Ejemplo n.º 16
0
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);
	VM_FREE(msg);
}
Ejemplo n.º 17
0
static struct eap_sim_pseudonym *
eap_sim_db_get_pseudonym(struct eap_sim_db_data *data, const u8 *identity,
			 size_t identity_len)
{
	char *pseudonym;
	size_t len;
	struct eap_sim_pseudonym *p;

	if (identity_len == 0 ||
	    (identity[0] != EAP_SIM_PSEUDONYM_PREFIX &&
	     identity[0] != EAP_AKA_PSEUDONYM_PREFIX))
		return NULL;

	/* Remove possible realm from identity */
	len = 0;
	while (len < identity_len) {
		if (identity[len] == '@')
			break;
		len++;
	}

	pseudonym = VM_MALLOC(len + 1);
	if (pseudonym == NULL)
		return NULL;
	memcpy(pseudonym, identity, len);
	pseudonym[len] = '\0';

	p = data->pseudonyms;
	while (p) {
		if (strcmp(p->pseudonym, pseudonym) == 0)
			break;
		p = p->next;
	}

	VM_FREE(pseudonym);

	return p;
}
Ejemplo n.º 18
0
static struct eap_sim_reauth *
eap_sim_db_get_reauth(struct eap_sim_db_data *data, const u8 *identity,
		      size_t identity_len)
{
	char *reauth_id;
	size_t len;
	struct eap_sim_reauth *r;

	if (identity_len == 0 ||
	    (identity[0] != EAP_SIM_REAUTH_ID_PREFIX &&
	     identity[0] != EAP_AKA_REAUTH_ID_PREFIX))
		return NULL;

	/* Remove possible realm from identity */
	len = 0;
	while (len < identity_len) {
		if (identity[len] == '@')
			break;
		len++;
	}

	reauth_id = VM_MALLOC(len + 1);
	if (reauth_id == NULL)
		return NULL;
	memcpy(reauth_id, identity, len);
	reauth_id[len] = '\0';

	r = data->reauths;
	while (r) {
		if (strcmp(r->reauth_id, reauth_id) == 0)
			break;
		r = r->next;
	}

	VM_FREE(reauth_id);

	return r;
}
Ejemplo n.º 19
0
static void radius_server_session_free(struct radius_server_data *data,
				       struct radius_session *sess)
{
	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
	VM_FREE(sess->eapKeyData);
	VM_FREE(sess->eapReqData);
	eap_sm_deinit(sess->eap);
	if (sess->last_msg) {
		radius_msg_free(sess->last_msg);
		VM_FREE(sess->last_msg);
	}
	VM_FREE(sess->last_from_addr);
	if (sess->last_reply) {
		radius_msg_free(sess->last_reply);
		VM_FREE(sess->last_reply);
	}
	VM_FREE(sess);
	data->num_sess--;
}
Ejemplo n.º 20
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 from;
	socklen_t fromlen;
	int len;
	struct radius_client *client = NULL;
	struct radius_msg *msg = NULL;
	char abuf[50];
	int from_port = 0;

	buf = VM_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;
		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);
		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;
	}

	VM_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);
		VM_FREE(msg);
	}
	VM_FREE(buf);
}
Ejemplo n.º 21
0
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 = VM_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 && hostapd_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 = VM_STRDUP(pos);
		if (entry->shared_secret == NULL) {
			failed = 1;
			VM_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;
	}

	VM_FREE(buf);
	fclose(f);

	return clients;
}
Ejemplo n.º 22
0
/**
 * eap_sim_db_get_aka_auth - Get AKA authentication values
 * @priv: Private data pointer from eap_sim_db_init()
 * @identity: User name identity
 * @identity_len: Length of identity in bytes
 * @_rand: Buffer for RAND value
 * @autn: Buffer for AUTN value
 * @ik: Buffer for IK value
 * @ck: Buffer for CK value
 * @res: Buffer for RES value
 * @res_len: Buffer for RES length
 * @cb_session_ctx: Session callback context for get_complete_cb()
 * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not
 * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this
 * case, the callback function registered with eap_sim_db_init() will be
 * called once the results become available.
 *
 * In most cases, the user name is '0' | IMSI, i.e., 0 followed by the IMSI in
 * ASCII format.
 *
 * When using an external server for AKA authentication, this function can
 * always start a request and return EAP_SIM_DB_PENDING immediately if
 * authentication triplets are not available. Once the authentication data are
 * received, callback function registered with eap_sim_db_init() is called to
 * notify EAP state machine to reprocess the message. This
 * eap_sim_db_get_aka_auth() function will then be called again and the newly
 * received triplets will then be given to the caller.
 */
int eap_sim_db_get_aka_auth(void *priv, const u8 *identity,
			    size_t identity_len, u8 *_rand, u8 *autn, u8 *ik,
			    u8 *ck, u8 *res, size_t *res_len,
			    void *cb_session_ctx)
{
	struct eap_sim_db_data *data = priv;
	struct eap_sim_db_pending *entry;
	int len;
	size_t i;
	char msg[40];

	if (identity_len < 2 || identity == NULL ||
	    identity[0] != EAP_AKA_PERMANENT_PREFIX) {
		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
				  identity, identity_len);
		return EAP_SIM_DB_FAILURE;
	}
	identity++;
	identity_len--;
	for (i = 0; i < identity_len; i++) {
		if (identity[i] == '@') {
			identity_len = i;
			break;
		}
	}
	if (identity_len + 1 > sizeof(entry->imsi)) {
		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
				  identity, identity_len);
		return EAP_SIM_DB_FAILURE;
	}
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI",
			  identity, identity_len);

	entry = eap_sim_db_get_pending(data, identity, identity_len, 1);
	if (entry) {
		if (entry->state == FAILURE) {
			VM_FREE(entry);
			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
			return EAP_SIM_DB_FAILURE;
		}

		if (entry->state == PENDING) {
			eap_sim_db_add_pending(data, entry);
			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending");
			return EAP_SIM_DB_PENDING;
		}

		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully "
			   "received authentication data");
		memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN);
		memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN);
		memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN);
		memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
		memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
		*res_len = entry->u.aka.res_len;
		VM_FREE(entry);
		return 0;
	}

	if (data->sock < 0) {
		if (eap_sim_db_open_socket(data) < 0)
			return EAP_SIM_DB_FAILURE;
	}

	len = snprintf(msg, sizeof(msg), "AKA-REQ-AUTH ");
	if (len < 0 || len + identity_len >= sizeof(msg))
		return EAP_SIM_DB_FAILURE;
	memcpy(msg + len, identity, identity_len);
	len += identity_len;

	wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication "
		    "data for IMSI", identity, identity_len);
	if (eap_sim_db_send(data, msg, len) < 0)
		return EAP_SIM_DB_FAILURE;

	entry = wpa_zalloc(sizeof(*entry));
	if (entry == NULL)
		return EAP_SIM_DB_FAILURE;

	os_get_time(&entry->timestamp);
	entry->aka = 1;
	memcpy(entry->imsi, identity, identity_len);
	entry->imsi_len = identity_len;
	entry->cb_session_ctx = cb_session_ctx;
	entry->state = PENDING;
	eap_sim_db_add_pending(data, entry);
	eap_sim_db_expire_pending(data);

	return EAP_SIM_DB_PENDING;
}
Ejemplo n.º 23
0
static void eap_vendor_test_reset(struct eap_sm *sm, void *priv)
{
	struct eap_vendor_test_data *data = priv;
	VM_FREE(data);
}
Ejemplo n.º 24
0
/**
 * eap_sim_db_get_gsm_triplets - Get GSM triplets
 * @priv: Private data pointer from eap_sim_db_init()
 * @identity: User name identity
 * @identity_len: Length of identity in bytes
 * @max_chal: Maximum number of triplets
 * @_rand: Buffer for RAND values
 * @kc: Buffer for Kc values
 * @sres: Buffer for SRES values
 * @cb_session_ctx: Session callback context for get_complete_cb()
 * Returns: Number of triplets received (has to be less than or equal to
 * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or
 * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the
 * callback function registered with eap_sim_db_init() will be called once the
 * results become available.
 *
 * In most cases, the user name is '1' | IMSI, i.e., 1 followed by the IMSI in
 * ASCII format.
 *
 * When using an external server for GSM triplets, this function can always
 * start a request and return EAP_SIM_DB_PENDING immediately if authentication
 * triplets are not available. Once the triplets are received, callback
 * function registered with eap_sim_db_init() is called to notify EAP state
 * machine to reprocess the message. This eap_sim_db_get_gsm_triplets()
 * function will then be called again and the newly received triplets will then
 * be given to the caller.
 */
int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity,
				size_t identity_len, int max_chal,
				u8 *_rand, u8 *kc, u8 *sres,
				void *cb_session_ctx)
{
	struct eap_sim_db_data *data = priv;
	struct eap_sim_db_pending *entry;
	int len, ret;
	size_t i;
	char msg[40];

	if (identity_len < 2 || identity[0] != EAP_SIM_PERMANENT_PREFIX) {
		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
				  identity, identity_len);
		return EAP_SIM_DB_FAILURE;
	}
	identity++;
	identity_len--;
	for (i = 0; i < identity_len; i++) {
		if (identity[i] == '@') {
			identity_len = i;
			break;
		}
	}
	if (identity_len + 1 > sizeof(entry->imsi)) {
		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
				  identity, identity_len);
		return EAP_SIM_DB_FAILURE;
	}
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI",
			  identity, identity_len);

	entry = eap_sim_db_get_pending(data, identity, identity_len, 0);
	if (entry) {
		int num_chal;
		if (entry->state == FAILURE) {
			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
				   "failure");
			VM_FREE(entry);
			return EAP_SIM_DB_FAILURE;
		}

		if (entry->state == PENDING) {
			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
				   "still pending");
			eap_sim_db_add_pending(data, entry);
			return EAP_SIM_DB_PENDING;
		}

		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
			   "%d challenges", entry->u.sim.num_chal);
		num_chal = entry->u.sim.num_chal;
		if (num_chal > max_chal)
			num_chal = max_chal;
		memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN);
		memcpy(sres, entry->u.sim.sres, num_chal * EAP_SIM_SRES_LEN);
		memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
		VM_FREE(entry);
		return num_chal;
	}

	if (data->sock < 0) {
		if (eap_sim_db_open_socket(data) < 0)
			return EAP_SIM_DB_FAILURE;
	}

	len = snprintf(msg, sizeof(msg), "SIM-REQ-AUTH ");
	if (len < 0 || len + identity_len >= sizeof(msg))
		return EAP_SIM_DB_FAILURE;
	memcpy(msg + len, identity, identity_len);
	len += identity_len;
	ret = snprintf(msg + len, sizeof(msg) - len, " %d", max_chal);
	if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
		return EAP_SIM_DB_FAILURE;
	len += ret;

	wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication "
		    "data for IMSI", identity, identity_len);
	if (eap_sim_db_send(data, msg, len) < 0)
		return EAP_SIM_DB_FAILURE;

	entry = wpa_zalloc(sizeof(*entry));
	if (entry == NULL)
		return EAP_SIM_DB_FAILURE;

	os_get_time(&entry->timestamp);
	memcpy(entry->imsi, identity, identity_len);
	entry->imsi_len = identity_len;
	entry->cb_session_ctx = cb_session_ctx;
	entry->state = PENDING;
	eap_sim_db_add_pending(data, entry);
	eap_sim_db_expire_pending(data);

	return EAP_SIM_DB_PENDING;
}
Ejemplo n.º 25
0
static void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
				     const char *imsi, char *buf)
{
	char *start, *end;
	struct eap_sim_db_pending *entry;

	/*
	 * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
	 * AKA-RESP-AUTH <IMSI> FAILURE
	 * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string)
	 */

	entry = eap_sim_db_get_pending(data, (u8 *) imsi, strlen(imsi), 1);
	if (entry == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
			   "received message found");
		return;
	}

	start = buf;
	if (strncmp(start, "FAILURE", 7) == 0) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
			   "failure");
		entry->state = FAILURE;
		eap_sim_db_add_pending(data, entry);
		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
		return;
	}

	end = strchr(start, ' ');
	if (end == NULL)
		goto parse_fail;
	*end = '\0';
	if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN))
		goto parse_fail;

	start = end + 1;
	end = strchr(start, ' ');
	if (end == NULL)
		goto parse_fail;
	*end = '\0';
	if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN))
		goto parse_fail;

	start = end + 1;
	end = strchr(start, ' ');
	if (end == NULL)
		goto parse_fail;
	*end = '\0';
	if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN))
		goto parse_fail;

	start = end + 1;
	end = strchr(start, ' ');
	if (end == NULL)
		goto parse_fail;
	*end = '\0';
	if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN))
		goto parse_fail;

	start = end + 1;
	end = strchr(start, ' ');
	if (end)
		*end = '\0';
	else {
		end = start;
		while (*end)
			end++;
	}
	entry->u.aka.res_len = (end - start) / 2;
	if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES");
		entry->u.aka.res_len = 0;
		goto parse_fail;
	}
	if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len))
		goto parse_fail;

	entry->state = SUCCESS;
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
		   "successfully - callback");
	eap_sim_db_add_pending(data, entry);
	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
	return;

parse_fail:
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
	VM_FREE(entry);
}
Ejemplo n.º 26
0
static void eap_sim_db_free_reauth(struct eap_sim_reauth *r)
{
	VM_FREE(r->identity);
	VM_FREE(r->reauth_id);
	VM_FREE(r);
}
Ejemplo n.º 27
0
static void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p)
{
	VM_FREE(p->identity);
	VM_FREE(p->pseudonym);
	VM_FREE(p);
}
Ejemplo n.º 28
0
static int radius_server_request(struct radius_server_data *data,
				 struct radius_msg *msg,
				 struct sockaddr *from, socklen_t fromlen,
				 struct radius_client *client,
				 const char *from_addr, int from_port,
				 struct radius_session *force_sess)
{
	u8 *eap = NULL;
	size_t eap_len;
	int res, state_included = 0;
	u8 statebuf[4], resp_id;
	unsigned int state;
	struct radius_session *sess;
	struct radius_msg *reply;
	struct eap_hdr *hdr;

	if (force_sess)
		sess = force_sess;
	else {
		res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
					  sizeof(statebuf));
		state_included = res >= 0;
		if (res == sizeof(statebuf)) {
			state = (statebuf[0] << 24) | (statebuf[1] << 16) |
				(statebuf[2] << 8) | statebuf[3];
			sess = radius_server_get_session(client, state);
		} else {
			sess = NULL;
		}
	}

	if (sess) {
		RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
	} else if (state_included) {
		RADIUS_DEBUG("State attribute included but no session found");
		radius_server_reject(data, client, msg, from, fromlen,
				     from_addr, from_port);
		return -1;
	} else {
		sess = radius_server_get_new_session(data, client, msg);
		if (sess == NULL) {
			RADIUS_DEBUG("Could not create a new session");
			radius_server_reject(data, client, msg, from, fromlen,
					     from_addr, from_port);
			return -1;
		}
	}

	if (sess->last_from_port == from_port &&
	    sess->last_identifier == msg->hdr->identifier &&
	    os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
	    0) {
		RADIUS_DEBUG("Duplicate message from %s", from_addr);
		data->counters.dup_access_requests++;
		client->counters.dup_access_requests++;

		if (sess->last_reply) {
			res = sendto(data->auth_sock, sess->last_reply->buf,
				     sess->last_reply->buf_used, 0,
				     (struct sockaddr *) from, fromlen);
			if (res < 0) {
				perror("sendto[RADIUS SRV]");
			}
			return 0;
		}

		RADIUS_DEBUG("No previous reply available for duplicate "
			     "message");
		return -1;
	}

	eap = radius_msg_get_eap(msg, &eap_len);
	if (eap == NULL) {
		RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
			     from_addr);
		data->counters.packets_dropped++;
		client->counters.packets_dropped++;
		return -1;
	}

	RADIUS_DUMP("Received EAP data", eap, eap_len);
	if (eap_len >= sizeof(*hdr)) {
		hdr = (struct eap_hdr *) eap;
		resp_id = hdr->identifier;
	} else {
		resp_id = 0;
	}

	/* FIX: if Code is Request, Success, or Failure, send Access-Reject;
	 * RFC3579 Sect. 2.6.2.
	 * Include EAP-Response/Nak with no preferred method if
	 * code == request.
	 * If code is not 1-4, discard the packet silently.
	 * Or is this already done by the EAP state machine? */

	eap_set_eapRespData(sess->eap, eap, eap_len);
	VM_FREE(eap);
	eap = NULL;
	sess->eapResp = TRUE;
	eap_sm_step(sess->eap);

	if (sess->eapReqData) {
		RADIUS_DUMP("EAP data from the state machine",
			    sess->eapReqData, sess->eapReqDataLen);
	} else if (sess->eapFail) {
		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
			     "set - generate EAP-Failure");
		hdr = wpa_zalloc(sizeof(*hdr));
		if (hdr) {
			hdr->identifier = resp_id;
			hdr->length = htons(sizeof(*hdr));
			sess->eapReqData = (u8 *) hdr;
			sess->eapReqDataLen = sizeof(*hdr);
		}
	} else if (eap_sm_method_pending(sess->eap)) {
		if (sess->last_msg) {
			radius_msg_free(sess->last_msg);
			VM_FREE(sess->last_msg);
		}
		sess->last_msg = msg;
		sess->last_from_port = from_port;
		VM_FREE(sess->last_from_addr);
		sess->last_from_addr = VM_STRDUP(from_addr);
		sess->last_fromlen = fromlen;
		memcpy(&sess->last_from, from, fromlen);
		return -2;
	} else {
		RADIUS_DEBUG("No EAP data from the state machine - ignore this"
			     " Access-Request silently (assuming it was a "
			     "duplicate)");
		data->counters.packets_dropped++;
		client->counters.packets_dropped++;
		return -1;
	}

	reply = radius_server_encapsulate_eap(data, client, sess, msg);

	VM_FREE(sess->eapReqData);
	sess->eapReqData = NULL;
	sess->eapReqDataLen = 0;

	if (reply) {
		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
		if (wpa_debug_level <= MSG_MSGDUMP) {
			radius_msg_dump(reply);
		}

		switch (reply->hdr->code) {
		case RADIUS_CODE_ACCESS_ACCEPT:
			data->counters.access_accepts++;
			client->counters.access_accepts++;
			break;
		case RADIUS_CODE_ACCESS_REJECT:
			data->counters.access_rejects++;
			client->counters.access_rejects++;
			break;
		case RADIUS_CODE_ACCESS_CHALLENGE:
			data->counters.access_challenges++;
			client->counters.access_challenges++;
			break;
		}
		res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
			     (struct sockaddr *) from, fromlen);
		if (res < 0) {
			perror("sendto[RADIUS SRV]");
		}
		if (sess->last_reply) {
			radius_msg_free(sess->last_reply);
			VM_FREE(sess->last_reply);
		}
		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->eapSuccess || sess->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;
}
Ejemplo n.º 29
0
static int hostapd_prepare_rates(struct hostapd_data *hapd,
				 struct hostapd_hw_modes *mode)
{
	int i, num_basic_rates = 0;
	int basic_rates_a[] = { 60, 120, 240, -1 };
	int basic_rates_b[] = { 10, 20, -1 };
	int basic_rates_g[] = { 10, 20, 55, 110, -1 };
	int *basic_rates;

	if (hapd->iconf->basic_rates)
		basic_rates = hapd->iconf->basic_rates;
	else switch (mode->mode) {
	case HOSTAPD_MODE_IEEE80211A:
		basic_rates = basic_rates_a;
		break;
	case HOSTAPD_MODE_IEEE80211B:
		basic_rates = basic_rates_b;
		break;
	case HOSTAPD_MODE_IEEE80211G:
		basic_rates = basic_rates_g;
		break;
	default:
		return -1;
	}

	if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
				  basic_rates, mode->mode)) {
		printf("Failed to update rate sets in kernel module\n");
	}

	VM_FREE(hapd->iface->current_rates);
	hapd->iface->num_rates = 0;

	hapd->iface->current_rates =
		VM_MALLOC(mode->num_rates * sizeof(struct hostapd_rate_data));
	if (!hapd->iface->current_rates) {
		printf("Failed to allocate memory for rate table.\n");
		return -1;
	}

	for (i = 0; i < mode->num_rates; i++) {
		struct hostapd_rate_data *rate;

		if (hapd->iconf->supported_rates &&
		    !hostapd_rate_found(hapd->iconf->supported_rates,
					mode->rates[i].rate))
			continue;

		rate = &hapd->iface->current_rates[hapd->iface->num_rates];
		memcpy(rate, &mode->rates[i],
		       sizeof(struct hostapd_rate_data));
		if (hostapd_rate_found(basic_rates, rate->rate)) {
			rate->flags |= HOSTAPD_RATE_BASIC;
			num_basic_rates++;
		} else
			rate->flags &= ~HOSTAPD_RATE_BASIC;
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "RATE[%d] rate=%d flags=0x%x\n",
			      hapd->iface->num_rates, rate->rate, rate->flags);
		hapd->iface->num_rates++;
	}

	if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
		printf("No rates remaining in supported/basic rate sets "
		       "(%d,%d).\n", hapd->iface->num_rates, num_basic_rates);
		return -1;
	}

	return 0;
}
Ejemplo n.º 30
0
static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
				     const char *imsi, char *buf)
{
	char *start, *end, *pos;
	struct eap_sim_db_pending *entry;
	int num_chal;

	/*
	 * SIM-RESP-AUTH <IMSI> Kc(i):SRES(i):RAND(i) ...
	 * SIM-RESP-AUTH <IMSI> FAILURE
	 * (IMSI = ASCII string, Kc/SRES/RAND = hex string)
	 */

	entry = eap_sim_db_get_pending(data, (u8 *) imsi, strlen(imsi), 0);
	if (entry == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
			   "received message found");
		return;
	}

	start = buf;
	if (strncmp(start, "FAILURE", 7) == 0) {
		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
			   "failure");
		entry->state = FAILURE;
		eap_sim_db_add_pending(data, entry);
		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
		return;
	}

	num_chal = 0;
	while (num_chal < EAP_SIM_MAX_CHAL) {
		end = strchr(start, ' ');
		if (end)
			*end = '\0';

		pos = strchr(start, ':');
		if (pos == NULL)
			goto parse_fail;
		*pos = '\0';
		if (hexstr2bin(start, entry->u.sim.kc[num_chal],
			       EAP_SIM_KC_LEN))
			goto parse_fail;

		start = pos + 1;
		pos = strchr(start, ':');
		if (pos == NULL)
			goto parse_fail;
		*pos = '\0';
		if (hexstr2bin(start, entry->u.sim.sres[num_chal],
			       EAP_SIM_SRES_LEN))
			goto parse_fail;

		start = pos + 1;
		if (hexstr2bin(start, entry->u.sim.rand[num_chal],
			       GSM_RAND_LEN))
			goto parse_fail;

		num_chal++;
		if (end == NULL)
			break;
		else
			start = end + 1;
	}
	entry->u.sim.num_chal = num_chal;

	entry->state = SUCCESS;
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
		   "successfully - callback");
	eap_sim_db_add_pending(data, entry);
	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
	return;

parse_fail:
	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
	VM_FREE(entry);
}