#include "EAPUtil.h"
#include "EAPOLUtil.h"
#include "printdata.h"
#include "nbo.h"
static bool
EAPOLPacketTypeValid(EAPOLPacketType type)
{
if (type >= kEAPOLPacketTypeEAPPacket
&& type <= kEAPOLPacketTypeEncapsulatedASFAlert) {
return (true);
}
return (false);
}
static const char *
EAPOLPacketTypeStr(EAPOLPacketType type)
{
static const char * str[] = {
"EAP Packet",
"Start",
"Logoff",
"Key",
"Encapsulated ASF Alert"
};
if (EAPOLPacketTypeValid(type)) {
return (str[type]);
}
return ("<unknown>");
}
static void
fprint_eapol_rc4_key_descriptor(FILE * f,
EAPOLRC4KeyDescriptorRef descr_p,
unsigned int body_length)
{
int key_data_length;
u_int16_t key_length;
const char * which;
if (descr_p->key_index & kEAPOLKeyDescriptorIndexUnicastFlag) {
which = "Unicast";
}
else {
which = "Broadcast";
}
key_length = EAPOLKeyDescriptorGetLength(descr_p);
key_data_length = body_length - sizeof(*descr_p);
fprintf(f, "EAPOL Key Descriptor: type RC4 (%d) length %d %s index %d\n",
descr_p->descriptor_type,
key_length,
which,
descr_p->key_index & kEAPOLKeyDescriptorIndexMask);
fprintf(f, "%-16s", "replay_counter:");
fprint_bytes(f, descr_p->replay_counter, sizeof(descr_p->replay_counter));
fprintf(f, "\n");
fprintf(f, "%-16s", "key_IV:");
fprint_bytes(f, descr_p->key_IV, sizeof(descr_p->key_IV));
fprintf(f, "\n");
fprintf(f, "%-16s", "key_signature:");
fprint_bytes(f, descr_p->key_signature, sizeof(descr_p->key_signature));
fprintf(f, "\n");
if (key_data_length > 0) {
fprintf(f, "%-16s", "key:");
fprint_bytes(f, descr_p->key, key_data_length);
fprintf(f, "\n");
}
return;
}
static void
fprint_eapol_ieee80211_key_descriptor(FILE * f,
EAPOLIEEE80211KeyDescriptorRef descr_p,
unsigned int body_length)
{
uint16_t key_data_length;
uint16_t key_information;
uint16_t key_length;
key_length = EAPOLIEEE80211KeyDescriptorGetLength(descr_p);
key_information = EAPOLIEEE80211KeyDescriptorGetInformation(descr_p);
key_data_length = EAPOLIEEE80211KeyDescriptorGetKeyDataLength(descr_p);
fprintf(f, "EAPOL Key Descriptor: type IEEE 802.11 (%d)\n",
descr_p->descriptor_type);
fprintf(f, "%-18s0x%04x\n", "key_information:", key_information);
fprintf(f, "%-18s%d\n", "key_length:", key_length);
fprintf(f, "%-18s", "replay_counter:");
fprint_bytes(f, descr_p->replay_counter, sizeof(descr_p->replay_counter));
fprintf(f, "\n");
fprintf(f, "%-18s", "key_nonce:");
fprint_bytes(f, descr_p->key_nonce, sizeof(descr_p->key_nonce));
fprintf(f, "\n");
fprintf(f, "%-18s", "EAPOL_key_IV:");
fprint_bytes(f, descr_p->EAPOL_key_IV, sizeof(descr_p->EAPOL_key_IV));
fprintf(f, "\n");
fprintf(f, "%-18s", "key_RSC:");
fprint_bytes(f, descr_p->key_RSC, sizeof(descr_p->key_RSC));
fprintf(f, "\n");
fprintf(f, "%-18s", "key_reserved:");
fprint_bytes(f, descr_p->key_reserved, sizeof(descr_p->key_reserved));
fprintf(f, "\n");
fprintf(f, "%-18s", "key_MIC:");
fprint_bytes(f, descr_p->key_MIC, sizeof(descr_p->key_MIC));
fprintf(f, "\n");
fprintf(f, "%-18s%d\n", "key_data_length:", key_data_length);
if (key_data_length > 0) {
fprintf(f, "%-18s", "key_data:");
fprint_bytes(f, descr_p->key_data, key_data_length);
fprintf(f, "\n");
}
return;
}
static bool
eapol_key_descriptor_valid(void * body, unsigned int body_length,
FILE * f)
{
EAPOLIEEE80211KeyDescriptorRef ieee80211_descr_p = body;
EAPOLRC4KeyDescriptorRef rc4_descr_p = body;
if (body_length < 1) {
if (f != NULL) {
fprintf(f, "eapol_key_descriptor_valid: body_length is %d < 1\n",
body_length);
}
return (false);
}
switch (rc4_descr_p->descriptor_type) {
case kEAPOLKeyDescriptorTypeRC4:
if (body_length < sizeof(*rc4_descr_p)) {
if (f != NULL) {
fprintf(f, "eapol_key_descriptor_valid: body_length %d"
" < sizeof(*rc4_descr_p) %ld\n",
body_length, sizeof(*rc4_descr_p));
}
return (false);
}
if (f != NULL) {
fprint_eapol_rc4_key_descriptor(f, rc4_descr_p, body_length);
}
break;
case kEAPOLKeyDescriptorTypeIEEE80211:
if (body_length < sizeof(*ieee80211_descr_p)) {
if (f != NULL) {
fprintf(f, "eapol_key_descriptor_valid: body_length %d"
" < sizeof(*ieee80211_descr_p) %ld\n",
body_length, sizeof(*ieee80211_descr_p));
}
return (false);
}
if (EAPOLIEEE80211KeyDescriptorGetKeyDataLength(ieee80211_descr_p)
> (body_length - sizeof(*ieee80211_descr_p))) {
if (f != NULL) {
fprintf(f, "eapol_key_descriptor_valid: key_data_length %d"
" > body_length - sizeof(*ieee80211_descr_p) %ld\n",
EAPOLIEEE80211KeyDescriptorGetKeyDataLength(ieee80211_descr_p),
body_length - sizeof(*ieee80211_descr_p));
}
return (false);
}
if (f != NULL) {
fprint_eapol_ieee80211_key_descriptor(f, ieee80211_descr_p,
body_length);
}
break;
default:
if (f != NULL) {
fprintf(f, "eapol_key_descriptor_valid: descriptor_type unknown %d",
rc4_descr_p->descriptor_type);
}
return (false);
}
return (true);
}
static bool
eapol_body_valid(EAPOLPacketRef eapol_p, unsigned int length, FILE * f)
{
unsigned int body_length;
bool ret = true;
body_length = EAPOLPacketGetLength(eapol_p);
length -= sizeof(*eapol_p);
if (length < body_length) {
if (f != NULL) {
fprintf(f, "packet length %d < body_length %d\n",
length, body_length);
}
return (false);
}
switch (eapol_p->packet_type) {
case kEAPOLPacketTypeEAPPacket:
ret = EAPPacketValid((EAPPacketRef)eapol_p->body, body_length, f);
break;
case kEAPOLPacketTypeKey:
ret = eapol_key_descriptor_valid(eapol_p->body, body_length, f);
break;
case kEAPOLPacketTypeStart:
case kEAPOLPacketTypeLogoff:
case kEAPOLPacketTypeEncapsulatedASFAlert:
break;
default:
if (f != NULL) {
fprintf(f, "unrecognized EAPOL packet type %d\n",
eapol_p->packet_type);
fprint_data(f, ((void *)eapol_p) + sizeof(*eapol_p), body_length);
}
break;
}
if (f != NULL) {
if (body_length < length) {
fprintf(f, "EAPOL: %d bytes follow body:\n", length - body_length);
fprint_data(f, ((void *)eapol_p) + sizeof(*eapol_p) + body_length,
length - body_length);
}
}
return (ret);
}
static bool
eapol_header_valid(EAPOLPacketRef eapol_p, unsigned int length,
FILE * f)
{
if (length < sizeof(*eapol_p)) {
if (f != NULL) {
fprintf(f, "Data length %d < sizeof(*eapol_p) %ld\n",
length, sizeof(*eapol_p));
}
return (false);
}
if (f != NULL) {
fprintf(f, "EAPOL: proto version 0x%x type %s (%d) length %d\n",
eapol_p->protocol_version,
EAPOLPacketTypeStr(eapol_p->packet_type),
eapol_p->packet_type, EAPOLPacketGetLength(eapol_p));
}
return (true);
}
bool
EAPOLPacketValid(EAPOLPacketRef eapol_p, unsigned int length, FILE * f)
{
if (eapol_header_valid(eapol_p, length, f) == false) {
return (false);
}
return (eapol_body_valid(eapol_p, length, f));
}
void
EAPOLPacketSetLength(EAPOLPacketRef pkt, uint16_t length)
{
net_uint16_set(pkt->body_length, length);
return;
}
uint16_t
EAPOLPacketGetLength(const EAPOLPacketRef pkt)
{
return (net_uint16_get(pkt->body_length));
}
void
EAPOLRC4KeyDescriptorSetLength(EAPOLRC4KeyDescriptorRef pkt, uint16_t length)
{
net_uint16_set(pkt->key_length, length);
return;
}
void
EAPOLKeyDescriptorSetLength(EAPOLKeyDescriptorRef pkt, uint16_t length)
{
EAPOLRC4KeyDescriptorSetLength(pkt, length);
return;
}
uint16_t
EAPOLRC4KeyDescriptorGetLength(const EAPOLRC4KeyDescriptorRef pkt)
{
return (net_uint16_get(pkt->key_length));
}
uint16_t
EAPOLKeyDescriptorGetLength(const EAPOLKeyDescriptorRef pkt)
{
return (EAPOLRC4KeyDescriptorGetLength(pkt));
}
uint16_t
EAPOLIEEE80211KeyDescriptorGetLength(const EAPOLIEEE80211KeyDescriptorRef pkt)
{
return (net_uint16_get(pkt->key_length));
}
uint16_t
EAPOLIEEE80211KeyDescriptorGetInformation(const EAPOLIEEE80211KeyDescriptorRef pkt)
{
return (net_uint16_get(pkt->key_information));
}
uint16_t
EAPOLIEEE80211KeyDescriptorGetKeyDataLength(const EAPOLIEEE80211KeyDescriptorRef pkt)
{
return (net_uint16_get(pkt->key_data_length));
}