eap_tlv.c

来自「hostapd无线AP工具」· C语言 代码 · 共 249 行

C
249
字号
/* * hostapd / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <netinet/in.h>#include "hostapd.h"#include "common.h"#include "eap_i.h"/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */#define EAP_TLV_NAK_TLV 4#define EAP_TLV_CRYPTO_BINDING_TLV 5#define EAP_TLV_CONNECTION_BINDING_TLV 6#define EAP_TLV_VENDOR_SPECIFIC_TLV 7#define EAP_TLV_URI_TLV 8#define EAP_TLV_EAP_PAYLOAD_TLV 9#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10#define EAP_TLV_RESULT_SUCCESS 1#define EAP_TLV_RESULT_FAILURE 2struct eap_tlv_data {	enum { CONTINUE, SUCCESS, FAILURE } state;};static void * eap_tlv_init(struct eap_sm *sm){	struct eap_tlv_data *data;	data = malloc(sizeof(*data));	if (data == NULL)		return data;	memset(data, 0, sizeof(*data));	data->state = CONTINUE;	return data;}static void eap_tlv_reset(struct eap_sm *sm, void *priv){	struct eap_tlv_data *data = priv;	free(data);}static u8 * eap_tlv_buildReq(struct eap_sm *sm, void *priv, int id,			     size_t *reqDataLen){	struct eap_hdr *req;	u8 *pos;	u16 status;	if (sm->tlv_request == TLV_REQ_SUCCESS) {		status = EAP_TLV_RESULT_SUCCESS;	} else {		status = EAP_TLV_RESULT_FAILURE;	}	*reqDataLen = sizeof(struct eap_hdr) + 1 + 6;	req = malloc(*reqDataLen);	if (req == NULL)		return NULL;	req->code = EAP_CODE_REQUEST;	req->identifier = id;	req->length = host_to_be16(*reqDataLen);	pos = (u8 *) (req + 1);	*pos++ = EAP_TYPE_TLV;	*pos++ = 0x80; /* Mandatory */	*pos++ = EAP_TLV_RESULT_TLV;	/* Length */	*pos++ = 0;	*pos++ = 2;	/* Status */	*pos++ = status >> 8;	*pos++ = status & 0xff;	return (u8 *) req;}static Boolean eap_tlv_check(struct eap_sm *sm, void *priv,			     u8 *respData, size_t respDataLen){	struct eap_hdr *resp;	u8 *pos;	size_t len;	resp = (struct eap_hdr *) respData;	pos = (u8 *) (resp + 1);	if (respDataLen < sizeof(*resp) + 1 || *pos != EAP_TYPE_TLV ||	    (len = ntohs(resp->length)) > respDataLen) {		wpa_printf(MSG_INFO, "EAP-TLV: Invalid frame");		return TRUE;	}	return FALSE;}static void eap_tlv_process(struct eap_sm *sm, void *priv,			    u8 *respData, size_t respDataLen){	struct eap_tlv_data *data = priv;	struct eap_hdr *resp;	u8 *pos;	int len;	size_t left;	u8 *result_tlv = NULL;	size_t result_tlv_len = 0;	int tlv_type, mandatory, tlv_len;	resp = (struct eap_hdr *) respData;	len = ntohs(resp->length);	pos = (u8 *) (resp + 1);	/* Parse TLVs */	left = be_to_host16(resp->length) - sizeof(struct eap_hdr) - 1;	pos = (u8 *) (resp + 1);	pos++;	wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);	while (left >= 4) {		mandatory = !!(pos[0] & 0x80);		tlv_type = pos[0] & 0x3f;		tlv_type = (tlv_type << 8) | pos[1];		tlv_len = ((int) pos[2] << 8) | pos[3];		pos += 4;		left -= 4;		if (tlv_len > left) {			wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "				   "(tlv_len=%d left=%lu)", tlv_len,				   (unsigned long) left);			data->state = FAILURE;			return;		}		switch (tlv_type) {		case EAP_TLV_RESULT_TLV:			result_tlv = pos;			result_tlv_len = tlv_len;			break;		default:			wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "				   "%d%s", tlv_type,				   mandatory ? " (mandatory)" : "");			if (mandatory) {				data->state = FAILURE;				return;			}			/* Ignore this TLV, but process other TLVs */			break;		}		pos += tlv_len;		left -= tlv_len;	}	if (left) {		wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "			   "Request (left=%lu)", (unsigned long) left);		data->state = FAILURE;		return;	}	/* Process supported TLVs */	if (result_tlv) {		int status;		const char *requested;		wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",			    result_tlv, result_tlv_len);		if (result_tlv_len < 2) {			wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "				   "(len=%lu)",				   (unsigned long) result_tlv_len);			data->state = FAILURE;			return;		}		requested = sm->tlv_request == TLV_REQ_SUCCESS ? "Success" :			"Failure";		status = ((int) result_tlv[0] << 8) | result_tlv[1];		if (status == EAP_TLV_RESULT_SUCCESS) {			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "				   "- requested %s", requested);			if (sm->tlv_request == TLV_REQ_SUCCESS)				data->state = SUCCESS;			else				data->state = FAILURE;					} else if (status == EAP_TLV_RESULT_FAILURE) {			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure - "				   "requested %s", requested);			if (sm->tlv_request == TLV_REQ_FAILURE)				data->state = SUCCESS;			else				data->state = FAILURE;		} else {			wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "				   "Status %d", status);			data->state = FAILURE;		}	}}static Boolean eap_tlv_isDone(struct eap_sm *sm, void *priv){	struct eap_tlv_data *data = priv;	return data->state != CONTINUE;}static Boolean eap_tlv_isSuccess(struct eap_sm *sm, void *priv){	struct eap_tlv_data *data = priv;	return data->state == SUCCESS;}const struct eap_method eap_method_tlv ={	.method = EAP_TYPE_TLV,	.name = "TLV",	.init = eap_tlv_init,	.reset = eap_tlv_reset,	.buildReq = eap_tlv_buildReq,	.check = eap_tlv_check,	.process = eap_tlv_process,	.isDone = eap_tlv_isDone,	.isSuccess = eap_tlv_isSuccess,};

⌨️ 快捷键说明

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