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 + -
显示快捷键?