📄 eapsim.c
字号:
/******************************************************************* * EAPOL Function implementations for supplicant * * Licensed under a dual GPL/BSD license. (See LICENSE file for more info.) * * File: eapsim.c * * Authors: Chris.Hessing@utah.edu * * $Id: eapsim.c,v 1.27 2006/06/01 22:49:50 galimorerpg Exp $ * $Date: 2006/06/01 22:49:50 $ * $Log: eapsim.c,v $ * Revision 1.27 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.26 2006/05/29 04:17:58 chessing * Fixes for some memory leaks. * * Revision 1.25 2006/04/25 01:17:44 chessing * LOTS of code cleanups, new error checking/debugging code added, and other misc. fixes/changes. * * Revision 1.24 2006/02/23 22:26:53 chessing * Fix for bug id #1415020. 'Building Xsupplicant 1.2.3 Fails on FC4'. * * Revision 1.23 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.) * * *******************************************************************//******************************************************************* * * The development of the EAP/SIM support was funded by Internet * Foundation Austria (http://www.nic.at/ipa) * *******************************************************************/#ifdef EAP_SIM_ENABLE // Only build this if it has been enabled.#include <inttypes.h>#include <openssl/hmac.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include "winscard.h"#include "profile.h"#include "xsupconfig.h"#include "eap.h"#include "eapsim.h"#include "sm_handler.h"#include "sim.h"#include "xsup_debug.h"#include "xsup_err.h"#ifdef USE_EFENCE#include <efence.h>#endifchar *do_sha1(char *tohash, int size){ EVP_MD_CTX ctx; char *hash_ret; int evp_ret_len; if (!xsup_assert((tohash != NULL), "tohash != NULL", FALSE)) return NULL; if (!xsup_assert((size > 0), "size > 0", FALSE)) return NULL; hash_ret = (char *)malloc(21); // We should get 20 bytes returned. if (!xsup_assert((hash_ret != NULL), "hash_ret != NULL", FALSE)) return NULL; EVP_DigestInit(&ctx, EVP_sha1()); EVP_DigestUpdate(&ctx, tohash, size); EVP_DigestFinal(&ctx, hash_ret, (int *)&evp_ret_len); if (evp_ret_len != 20) { debug_printf(DEBUG_NORMAL, "Invalid result from OpenSSL SHA calls! " "(%s:%d)\n", __FUNCTION__, __LINE__); return NULL; } return hash_ret;}int eapsim_get_username(struct interface_data *thisint){ char *imsi; char realm[25], card_mode=0; char *readers, *username; struct config_eap_sim *userdata; struct generic_eap_data mydata; struct config_network *network_data; SCARDCONTEXT ctx; SCARDHANDLE hdl; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; network_data = config_get_network_config(); if (!xsup_assert((network_data != NULL), "network_data != NULL", FALSE)) return XEBADCONFIG; if (!xsup_assert((network_data->methods != NULL), "network_data->methods != NULL", FALSE)) return XEMALLOC; userdata = (struct config_eap_sim *)network_data->methods->method_data; if (!xsup_assert((userdata != NULL), "userdata != NULL", FALSE)) return XEMALLOC; mydata.eap_conf_data = userdata; // Initalize our smartcard context, and get ready to authenticate. if (sm_handler_init_ctx(&ctx) != 0) { debug_printf(DEBUG_NORMAL, "Couldn't initialize smart card context!\n"); return XESIMGENERR; } readers = sm_handler_get_readers(&ctx); if (readers == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't find any valid card readers!\n"); return XESIMGENERR; } // Connect to the smart card. if (sm_handler_card_connect(&ctx, &hdl, readers) != 0) { debug_printf(DEBUG_NORMAL, "Error connecting to smart card reader!\n"); return XESIMGENERR; } // Wait for up to 10 seconds for the smartcard to become ready. if (sm_handler_wait_card_ready(&hdl, 10) != 0) { debug_printf(DEBUG_NORMAL, "Smart Card wasn't ready after 10 seconds!\n"); return XESIMGENERR; } imsi = sm_handler_2g_imsi(&hdl, card_mode, userdata->password); if (imsi == NULL) { debug_printf(DEBUG_NORMAL, "Error starting smart card, and getting IMSI!\n"); return XESIMGENERR; } debug_printf(DEBUG_AUTHTYPES, "SIM IMSI : %s\n",imsi); if (network_data->identity != NULL) { free(network_data->identity); } network_data->identity = (char *)malloc(256); if (network_data->identity == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for identity information! (%s:%d)\n", __FUNCTION__, __LINE__); return XEMALLOC; } username = network_data->identity; userdata->username = username; bzero(username, 50); username[0] = '1'; // An IMSI should always start with a 1. strncpy(&username[1], imsi, 18); if (userdata->auto_realm == TRUE) { bzero(&realm, 25); sprintf((char *)&realm, "@mnc%c%c%c.mcc%c%c%c.owlan.org", username[4], username[5], username[6], username[1], username[2], username[3]); debug_printf(DEBUG_AUTHTYPES, "Realm Portion : %s\n",realm); strcat(username, realm); } // Close the smartcard, so that we know what state we are in. sm_handler_close_sc(&hdl, &ctx); free(imsi); imsi = NULL; free(readers); readers = NULL; debug_printf(DEBUG_AUTHTYPES, "Username is now : %s\n", username); return XENONE;}int eapsim_setup(struct generic_eap_data *thisint){ struct eaptypedata *mydata; struct config_eap_sim *userdata; char *imsi; debug_printf(DEBUG_AUTHTYPES, "(EAP-SIM) Initalized\n"); if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; thisint->eap_data = (char *)malloc(sizeof(struct eaptypedata)); if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XEMALLOC; mydata = (struct eaptypedata *)thisint->eap_data; userdata = (struct config_eap_sim *)thisint->eap_conf_data; mydata->workingversion = 0; mydata->numrands = 0; mydata->verlistlen = 0; mydata->verlist = NULL; mydata->nonce_mt = NULL; mydata->keyingMaterial = NULL; bzero(&mydata->triplet[0], 3*sizeof(struct triplets)); thisint->eap_data = (void *)mydata; // Initalize our smartcard context, and get ready to authenticate. if (sm_handler_init_ctx(&mydata->scntx) != 0) { debug_printf(DEBUG_NORMAL, "Couldn't initialize smart card context!\n"); return XESIMGENERR; } mydata->readers = sm_handler_get_readers(&mydata->scntx); if (mydata->readers == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't find any readers attached to the system!\n"); return XESIMGENERR; } // Connect to the smart card. if (sm_handler_card_connect(&mydata->scntx, &mydata->shdl, mydata->readers) != 0) { debug_printf(DEBUG_NORMAL, "Error connecting to smart card reader!\n"); return XESIMGENERR; } // Wait for up to 20 seconds for the smartcard to become ready. if (sm_handler_wait_card_ready(&mydata->shdl, 20) != 0) { debug_printf(DEBUG_NORMAL, "Smart Card wasn't ready after 20 seconds!\n"); return XESIMGENERR; } imsi = sm_handler_2g_imsi(&mydata->shdl, mydata->card_mode, userdata->password); if (imsi == NULL) { debug_printf(DEBUG_NORMAL, "Error starting smart card, and getting IMSI!\n"); return XESIMGENERR; } if (userdata->username == NULL) { userdata->username = imsi; } else { free(imsi); imsi = NULL; } return XENONE;}int eapsim_process(struct generic_eap_data *thisint, uint8_t *dataoffs, int insize, uint8_t *out, int *outsize){ int packet_offset, outptr, value16, retval; struct typelength *typelen; struct eaptypedata *mydata; char nsres[16], *username, mac_calc[16], K_int[16]; struct config_eap_sim *userdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((dataoffs != NULL), "dataoffs != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((out != NULL), "out != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((outsize != NULL), "outsize != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XEMALLOC; mydata = (struct eaptypedata *)thisint->eap_data; userdata = (struct config_eap_sim *)thisint->eap_conf_data; bzero(nsres, 16); if (!userdata) { debug_printf(DEBUG_NORMAL, "Invalid user data struct in eapsim_process()!\n"); return XEMALLOC; } if ((thisint->tempPwd == NULL) && (userdata->password == NULL)) { thisint->need_password = 1; thisint->eaptype = strdup("EAP-SIM"); thisint->eapchallenge = NULL; *outsize = 0; return XENONE; } // Make sure we have something to process... if (dataoffs == NULL) return XENONE; if (userdata->username == NULL) { username = thisint->identity; } else { username = userdata->username; } if ((userdata->password == NULL) && (thisint->tempPwd != NULL)) { userdata->password = thisint->tempPwd; thisint->tempPwd = NULL; } *outsize = 0; bzero(&mac_calc[0], 16); switch (dataoffs[0]) { case SIM_START: retval = sim_build_start(mydata, out, &outptr); if (retval != XENONE) return retval; packet_offset = 3; // Process SIM value fields. while (packet_offset < insize) { switch (dataoffs[packet_offset]) { case AT_MAC: debug_printf(DEBUG_NORMAL, "You cannot have an AT_MAC in a Start packet!\n"); return XESIMNOATMAC; case AT_ANY_ID_REQ: case AT_FULLAUTH_ID_REQ: case AT_PERMANENT_ID_REQ: retval = sim_build_fullauth(username, dataoffs, &packet_offset, out, &outptr); if (retval != XENONE) return retval; break; case AT_VERSION_LIST: retval = sim_at_version_list(username, mydata, dataoffs, &packet_offset, out, &outptr); if (retval != XENONE) return retval; break; default: debug_printf(DEBUG_NORMAL, "Unknown SIM type! (%02X)\n", dataoffs[packet_offset]); return XESIMBADTYPE; } } // Write the length in the response header. value16 = htons(outptr); memcpy((char *)&out[1], &value16, 2); *outsize = (outptr); break; case SIM_CHALLENGE: debug_printf(DEBUG_AUTHTYPES, "Got SIM_CHALLENGE!\n"); packet_offset = 3; typelen = (struct typelength *)&out[0]; typelen->type = SIM_CHALLENGE; outptr = 3; while (packet_offset < insize) { switch (dataoffs[packet_offset]) { case AT_RAND: retval = sim_do_at_rand(mydata, username, (char *)&nsres, dataoffs, &packet_offset, out, &outptr, &K_int[0]); if (retval != XENONE) return retval; break; case AT_IV: debug_printf(DEBUG_AUTHTYPES, "Got an IV (Not supported)\n"); sim_skip_not_implemented(dataoffs, &packet_offset); break; case AT_ENCR_DATA: debug_printf(DEBUG_AUTHTYPES, "Got an AT_ENCR_DATA (Not supported)\n"); sim_skip_not_implemented(dataoffs, &packet_offset); break; case AT_MAC: retval = sim_do_at_mac(thisint, mydata, dataoffs, insize, &packet_offset, out, &outptr, &K_int[0]); if (retval != XENONE) return retval; break; } } if (mydata->workingversion == 1) { debug_printf(DEBUG_NORMAL, "nsres = "); debug_hex_printf(DEBUG_NORMAL, nsres, 12); retval = sim_do_v1_response(thisint, out, &outptr, (char *)&nsres, &K_int[0]); if (retval != XENONE) return retval; } value16 = htons(outptr); memcpy((char *)&out[1], &value16, 2); *outsize = outptr; break; case SIM_NOTIFICATION: debug_printf(DEBUG_NORMAL, "Got SIM_NOTIFICATION! (Unsupported)\n"); break; case SIM_REAUTHENTICATION: debug_printf(DEBUG_NORMAL, "Got SIM_REAUTHENTICATION! (Unsupported)\n"); break; default: debug_printf(DEBUG_NORMAL, "Unknown SubType value! (%d)\n", dataoffs[0]); break; } out[2] = 0; return XENONE;}int eapsim_get_keys(struct interface_data *thisint){ struct eaptypedata *mydata; struct config_network *network_data; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; network_data = config_get_network_config(); if (!xsup_assert((network_data != NULL), "network_data != NULL", FALSE)) return XEMALLOC; mydata = (struct eaptypedata *)network_data->activemethod->eap_data; if (thisint->keyingMaterial != NULL) { free(thisint->keyingMaterial); } thisint->keyingMaterial = (char *)malloc(64); if (thisint->keyingMaterial == NULL) { debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for keying " "material! (%s:%d)\n", __FUNCTION__, __LINE__); return XEMALLOC; } memcpy(thisint->keyingMaterial, mydata->keyingMaterial, 64); thisint->keyingLength = 32; return XENONE;}int eapsim_failed(struct generic_eap_data *thisint){ struct config_eap_sim *userdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_conf_data != NULL), "thisint->eap_conf_data != NULL", FALSE)) return XEMALLOC; userdata = (struct config_eap_sim *)thisint->eap_conf_data;#ifndef NO_PWD_RESET /* if (userdata->password != NULL) { free(userdata->password); userdata->password = NULL; } */#endif return XENONE;}int eapsim_cleanup(struct generic_eap_data *thisint){ struct eaptypedata *mydata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; debug_printf(DEBUG_AUTHTYPES, "(EAP-SIM) Cleaning up!\n"); mydata = (struct eaptypedata *)thisint->eap_data; sm_handler_close_sc(&mydata->shdl, &mydata->scntx); return XENONE;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -