📄 peap_phase2.c
字号:
/******************************************************************* * PEAP phase 2 implementation. * * Licensed under a dual GPL/BSD license. (See LICENSE file for more info.) * * File: peap_phase2.c * * Authors: Chris.Hessing@utah.edu * * $Id: peap_phase2.c,v 1.34 2006/06/01 22:49:50 galimorerpg Exp $ * $Date: 2006/06/01 22:49:50 $ * $Log: peap_phase2.c,v $ * Revision 1.34 2006/06/01 22:49:50 galimorerpg * Converted all instances of u_char to uint8_t * Fixed a bad #include in the generic frame handler. * * Revision 1.33 2006/05/31 17:36:20 chessing * Some potential buffer overflow fixes, and memory leak patches from Carsten Grohmann. * * Revision 1.32 2006/05/30 16:56:31 chessing * More patches from Carsten Grohmann and a #if that was missing from the 1.2.5 release. * * Revision 1.31 2006/05/29 04:17:58 chessing * Fixes for some memory leaks. * * Revision 1.30 2006/05/24 18:42:22 chessing * Small fix from Carsten Grohman, and a few little fixes/changes from me. * * Revision 1.29 2006/05/22 22:29:17 chessing * Compiler warnings patches from Eric Evans. (And one from me. ;) * * Revision 1.28 2006/04/25 01:17:44 chessing * LOTS of code cleanups, new error checking/debugging code added, and other misc. fixes/changes. * * Revision 1.27 2006/03/28 21:16:07 chessing * Fixes to EAP-AKA, and PEAP. PEAP now handles inner success messages, and works with Funk SBR. * * Revision 1.26 2005/10/17 03:56:54 chessing * Updates to the libxsupconfig library. It no longer relies on other source from the main tree, so it can be used safely in other code with problems. * * Revision 1.25 2005/10/14 02:26:18 shaftoe * - cleanup gcc 4 warnings * - (re)add support for a pid in the form of /var/run/xsupplicant.<iface>.pid * * -- Eric Evans <eevans@sym-link.com> * * Revision 1.24 2005/08/09 01:39:17 chessing * Cleaned out old commit notes from the released version. Added a few small features including the ability to disable the friendly warnings that are spit out. (Such as the warning that is displayed when keys aren't rotated after 10 minutes.) We should also be able to start when the interface is down. Last, but not least, we can handle empty network configs. (This may be useful for situations where there isn't a good reason to have a default network defined.) * * *******************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <netinet/in.h>#include "xsupconfig.h"#include "profile.h"#include "eap.h"#include "peap_phase2.h"#include "eappeap.h"#include "../tls/eaptls.h"#include "xsup_err.h"#include "xsup_debug.h"#include "../mschapv2/eapmschapv2.h"#include "../otp/eapotp.h"#include "../tls/tls_crypt.h"#ifdef USE_EFENCE#include <efence.h>#endif#define VALID_EAP_TYPE EAP_TYPE_MSCHAP#define HIGHEST_PEAP_SUPPORTED 1int set_peap_version(struct phase2_data *p2d, int new_version){ if (!xsup_assert((p2d != NULL), "p2d != NULL", FALSE)) return XEMALLOC; if (new_version > HIGHEST_PEAP_SUPPORTED) { p2d->peap_version = HIGHEST_PEAP_SUPPORTED; return HIGHEST_PEAP_SUPPORTED; } /* Only change versions if we are changing to a higher one. This will * * keep us from backing off to a lower version mid-communication, should * * the RADIUS server get confused. */ if (p2d->peap_version < new_version) { debug_printf(DEBUG_AUTHTYPES, "PEAP Version changed to %d\n",new_version); p2d->peap_version = new_version; } return p2d->peap_version;}/* Remove the beginning 18 bytes. */void peap_unpad_frame(uint8_t *in, int in_size, uint8_t *out, int *out_size){ int i; if (!xsup_assert((in != NULL), "in != NULL", FALSE)) return; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return; if (!xsup_assert((out_size != NULL), "out_size != NULL", FALSE)) return; if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "Packet too large in peap_unpad_frame()!\n"); return; } *out_size = in_size - 4; for (i=0;i<=*out_size;i++) { out[i] = in[4+i]; }}/* Pad out the beginning with 18 bytes. (Probably 0s.) */void peap_pad_frame(uint8_t *in, int in_size, uint8_t *out, int *out_size){ int i; if (!xsup_assert((in != NULL), "in != NULL", FALSE)) return; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return; if (!xsup_assert((out_size != NULL), "out_size != NULL", FALSE)) return; if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "In packet size to large! Ignoring!\n"); return; } *out_size = in_size + 4; bzero(out, *out_size); for (i=0;i<=in_size;i++) { out[4+i] = in[i]; }}int do_peap_version1(struct phase2_data *thisint, uint8_t *in, int in_size, uint8_t *out, int *out_size){ uint8_t *padded_frame = NULL; int eapvalue, eapid, padded_size = 0, retval = XENONE; struct tls_vars *mytls_vars; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out_size != NULL), "out_size != NULL", FALSE)) return XEMALLOC; if (in_size > 1520) { debug_printf(DEBUG_NORMAL, "Invalid frame passed in to do_peap_version1()!\n"); return XEINVALIDEAP; } if (in_size < 5) { /* We don't have enough information to parse this, so it is probably * * in PEAP v0 format. So, pad it out. */ padded_size = in_size; padded_frame = (uint8_t *)malloc(in_size+19); /* It is 19 bytes to pad out. */ if (padded_frame == NULL) { debug_printf(DEBUG_NORMAL, "Unable to allocate memory for padded_frame in do_peap_version1()!\n"); return XEMALLOC; } peap_pad_frame(in, in_size, padded_frame, &padded_size); in = padded_frame; in_size = padded_size; } *out_size = 0; mytls_vars = (struct tls_vars *)thisint->eapdata->eap_data; /* mytls_vars may be NULL here! This is okay, as long as we aren't in the * * middle of an inner authentication. */ eapvalue = in[4]; eapid = in[5]; /* Inner EAP id. */ debug_printf(DEBUG_AUTHTYPES, "Inner packet : \n"); if (in_size < 1522) { debug_hex_dump(DEBUG_AUTHTYPES, in, in_size); } else { debug_printf(DEBUG_AUTHTYPES, "INVALID PACKET SIZE!\n"); } switch ((uint8_t)eapvalue) { case EAP_REQUEST: eap_request_id(thisint->eapdata->identity, eapid, (char *) out, out_size); break; case EAP_SUCCESS: debug_printf(DEBUG_AUTHTYPES, "Got a phase 2 success!\n"); bzero(out, 5); *out_size = 1; retval = XINNERSUCCESS; break; case PEAP_EAP_EXTENSION: /* EAP Extension */ debug_printf(DEBUG_AUTHTYPES, "Got an EAP extension frame!\n"); out[0] = EAP_RESPONSE; memcpy(&out[1], &in[1], in_size-1); *out_size = in_size; break; case EAP_FAILURE: debug_printf(DEBUG_AUTHTYPES, "Got a phase 2 failure.\n"); retval = XEINNERFAILED; break; default: if (eap_create_active_method(&thisint->activemethod, thisint->eapdata->identity, thisint->eapdata->tempPwd, thisint->eapdata->intName) != 0) { debug_printf(DEBUG_NORMAL, "Couldn't build active method! Phase 2 " "authentication will not happen!\n"); return XENOBUFFER; } eap_request_auth(thisint->activemethod, thisint->eapdata->eap_conf_data, (char *) in, in_size, (char *) out, out_size); break; } if (padded_size > 0) free(padded_frame); return retval;}int do_peap_version0(struct phase2_data *thisint, uint8_t *in, int in_size, uint8_t *out, int *out_size){ char *padded_frame = NULL; char *new_frame = NULL; int padded_size, new_frame_size, eframe = 0; int retval = XENONE; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out_size != NULL), "out_size != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((in != NULL), "in != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return XEMALLOC; *out_size = 0; if (in_size>1520) { debug_printf(DEBUG_NORMAL, "Input frame is too big! Ignoring!\n"); *out_size = 0; retval = XEMALLOC; goto out; } padded_size = in_size; padded_frame = (char *)malloc(in_size+19); // It is 19 bytes to pad out. if (padded_frame == NULL) { debug_printf(DEBUG_NORMAL, "Unable to allocate memory for padded_frame " "in %s()!\n", __FUNCTION__); retval = XEMALLOC; goto out; } if ((in[4] == 0x21) && (in[5] == 0x80) && !(thisint->eapdata->ias_quirk == 1 && in[0] == EAP_TYPE_MSCHAPV2)) { eframe = 1; memcpy(padded_frame, in, in_size); } if (eframe != 1) { peap_pad_frame(in, in_size, (uint8_t *) padded_frame, &padded_size); } new_frame = (char *)malloc(1024); if (new_frame == NULL) { debug_printf(DEBUG_NORMAL, "ACK! We can't allocate memory!\n"); retval = XEMALLOC; goto out; } retval = do_peap_version1(thisint, (uint8_t *) padded_frame, padded_size, (uint8_t *) new_frame, &new_frame_size); if (eframe != 1) { peap_unpad_frame((uint8_t *) new_frame, new_frame_size, out, out_size); } else { memcpy(out, new_frame, new_frame_size); *out_size = new_frame_size; } out: if (new_frame != NULL) { free(new_frame); } if (padded_frame != NULL) { free(padded_frame); } return retval;}int peap_do_phase2(struct generic_eap_data *thisint, uint8_t *in, int in_size, uint8_t *out, int *out_size){ struct tls_vars *mytls_vars; struct phase2_data *p2d; uint8_t *decr_data = NULL; uint8_t *encr_data = NULL; int encrsize = 0; int decrsize = 0; int retval = XENONE; struct config_eap_peap *peapconf; struct generic_eap_data *eapdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((in != NULL), "in != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out_size != NULL), "out_size != NULL", FALSE)) return XEMALLOC; *out_size = 0; mytls_vars = (struct tls_vars *)thisint->eap_data; if (mytls_vars == NULL) { debug_printf(DEBUG_NORMAL, "mytls_vars (thisint->eap_data) == NULL!\n"); return XEGENERROR; } peapconf = (struct config_eap_peap *)thisint->eap_conf_data; if (!xsup_assert((peapconf != NULL), "peapconf != NULL", FALSE)) return XEGENERROR; p2d = (struct phase2_data *)mytls_vars->phase2data; if (!xsup_assert((p2d != NULL), "p2d != NULL", FALSE)) return XEGENERROR; if (p2d->eapdata == NULL) { p2d->eapdata = (struct generic_eap_data *)malloc(sizeof(struct generic_eap_data)); if (p2d->eapdata == NULL) { *out_size = 0; return XEGENERROR; } memset(p2d->eapdata, 0, sizeof(struct generic_eap_data)); p2d->eapdata->eap_data = NULL; } p2d->eapdata->eap_conf_data = peapconf->phase2; /* XXX Clean up! */ if (peapconf->identity == NULL) debug_printf(DEBUG_NORMAL, "peapconf->identity is NULL!\n"); p2d->eapdata->identity = peapconf->identity; p2d->eapdata->ias_quirk = peapconf->ias_quirk; decr_data = (uint8_t *)malloc(1550); if (decr_data == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for decryption buffer!\n"); return XEMALLOC; } encr_data = (uint8_t *)malloc(1550); if (encr_data == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for encryption buffer!\n"); free(decr_data); return XEMALLOC; } if (in_size > 0) { if (tls_crypt_decrypt(thisint, in, in_size, decr_data, &decrsize) != XENONE) { debug_printf(DEBUG_AUTHTYPES, "Decryption failed.\n"); bzero(in, 50); /* Zero enough to keep us from processing this * * again. */ *out_size = 0; if (encr_data != NULL) free(encr_data); if (decr_data != NULL) free(decr_data); return XETLSCRYPTFAIL; } debug_printf(DEBUG_AUTHTYPES, "Decrypted dump : \n"); debug_hex_dump(DEBUG_AUTHTYPES, decr_data, decrsize); } else { if (decr_data != NULL) { free(decr_data); decr_data = NULL; } } /* We need to check this. I don't think it is needed anymore. */ if (decrsize <=0) { debug_printf(DEBUG_AUTHTYPES, "Sending ACK!\n"); bzero(out,10); *out_size = 1; if (decr_data != NULL) free(decr_data); if (encr_data != NULL) free(encr_data); return XENONE; } debug_printf(DEBUG_AUTHTYPES, "Decrypted packet returned %d byte(s)\n", decrsize); if (thisint->tempPwd != NULL) { eapdata = p2d->eapdata; if (eapdata != NULL) { eapdata->tempPwd = thisint->tempPwd; } } bzero(out, 100); switch (p2d->peap_version) { case 0: debug_printf(DEBUG_AUTHTYPES, "Doing PEAP v0!\n"); retval = do_peap_version0(p2d, decr_data, decrsize, encr_data, &encrsize); break; case 1: debug_printf(DEBUG_AUTHTYPES, "Doing PEAP v1!\n"); retval = do_peap_version1(p2d, decr_data, decrsize, encr_data, &encrsize); break; default: debug_printf(DEBUG_NORMAL, "Unknown PEAP version! (%d)\n",p2d->peap_version); break; } eapdata = p2d->eapdata; if (eapdata->need_password == 1) { thisint->need_password = 1; thisint->eaptype = eapdata->eaptype; thisint->eapchallenge = eapdata->eapchallenge; *out_size = 0; } if (encrsize > 0) { debug_printf(DEBUG_AUTHTYPES, "Unencrypted return frame : \n"); debug_hex_dump(DEBUG_AUTHTYPES, encr_data, encrsize); tls_crypt_encrypt_nolen(thisint, encr_data, encrsize, out, out_size); debug_printf(DEBUG_AUTHTYPES, "Encrypted return frame : \n"); debug_hex_dump(DEBUG_AUTHTYPES, out, *out_size); } if (encr_data != NULL) free(encr_data); if (decr_data != NULL) free(decr_data); return retval;}void peap_phase2_failed(struct generic_eap_data *thisint){ struct tls_vars *mytls_vars; struct phase2_data *p2d; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return; mytls_vars = (struct tls_vars *)thisint->eap_data; if (mytls_vars == NULL) { debug_printf(DEBUG_NORMAL, "mytls_vars (thisint->eap_data) == NULL!\n"); return; } p2d = (struct phase2_data *)mytls_vars->phase2data; if (p2d->eapdata == NULL) { /* We didn't get to phase 2, so just bail. */ return; } eap_do_fail(p2d->activemethod);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -