📄 cardif_linux.c
字号:
/** * A client-side 802.1x implementation * * This code is released under both the GPL version 2 and BSD licenses. * Either license may be used. The respective licenses are found below. * * Copyright (C) 2002 Bryan D. Payne & Nick L. Petroni Jr. * All Rights Reserved * * --- GPL Version 2 License --- * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * --- BSD License --- * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * Maryland at College Park and its contributors. * - Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//******************************************************************* * The driver function for a Linux application layer EAPOL * implementation * File: cardif_linux.c * * Authors: Chris.Hessing@utah.edu * * $Id: cardif_linux.c,v 1.43 2004/08/20 04:42:28 chessing Exp $ * $Date: 2004/08/20 04:42:28 $ * $Log: cardif_linux.c,v $ * Revision 1.43 2004/08/20 04:42:28 chessing * Set all of the new scanning and WPA code to be disabled by default, so that a 1.0.1 release can be made. Added additional error message output to AKA code. Fixed a few memory leaks in the AKA code. * * Revision 1.42 2004/08/19 04:11:48 chessing * More updates to get closer to WPA support. We can now associate to an AP that has WPA, however we are using a static WPA IE, so that needs to be fixed. There is also still a fair bit of other things that need to be cleaned up, but we are closer. * * Revision 1.41 2004/08/19 02:28:07 chessing * First piece of WPA patch. (The patch is growing fast, and this commit is to save what is done so far.) * * Revision 1.40 2004/08/16 23:36:28 chessing * Cosmetic fixes and trapping of an error that popped up. * * Revision 1.39 2004/08/16 01:56:44 chessing * * A few more updates to last nights patch. * * Revision 1.38 2004/08/15 04:29:35 chessing * * Completed support for scanning and joining wireless networks. If your interface isn't configured, we will scan to gather information about all known wireless networks. If a network in the list has a configuration, we will join it. (Including turning on needed encryption.) There are still a few rough edges that need to be hammered out. But the overall user experience should be improved. * * Revision 1.37 2004/08/12 01:40:06 chessing * * Added "association" option to the global configuration file sections. It can be set to either auto, or manual. Setting "association" to auto means that XSupplicant will attempt to associate to a network with the lowest value in the "priority" setting. The default for "association" is auto. The other option added is "priority" which is a numeric value from 1..256. A value of 1 is the highest priority, and will be the first network chosen. (Assuming the network can be found in a scan.) The default value for "priority" is 0, which means that network will be checked last. -- Although the options are now in the config file, the actual functionality for auto association/priority is not yet complete. (So, basically these options don't do anything yet. ;) * * Revision 1.36 2004/08/10 01:59:26 chessing * * Added support for the SNMP supplicant counters defined in the IEEE 802.1X-2001 document. * * Revision 1.35 2004/08/05 23:56:21 chessing * * Added basic support for scanning for broadcast SSIDs. This is another step closer to WPA/11i support. ;) * * Revision 1.34 2004/07/26 03:08:58 chessing * * Fixed a few bugs in the new hot plug code. Hot unplugging (and replugging) now works. * * Revision 1.33 2004/07/25 19:36:41 chessing * Fixed a few more logical/bitwise nots. Added rtnetlink support for hot-plugging interfaces. (Hot unplugging is coming soon. ;) * * Revision 1.32 2004/07/23 04:05:50 chessing * Fixed a segfault problem. Started to add rtnetlink support. * * Revision 1.31 2004/07/22 22:35:07 chessing * * Changed cardif pieces to build as an intermediate module, to allow it to be defined in more than one file. These changes should help make things more portable. * * Revision 1.30 2004/07/21 22:47:53 chessing * * Fixed bitwise not problem identified in bugid 995523. * * Revision 1.29 2004/07/19 02:43:16 chessing * * Changed things to get rid of Linux specific pieces in the interface_data struct. Fixed up EAP-SIM and EAP-AKA to skip AVPs that we don't support. (We print a mesage, and move on.) Added the --enable-radiator-test option to configure EAP-AKA to use the test vectors included with Radiator's AKA module. (To use this mode, no SIM card is required, but the PCSC library is still needed to build. Also, some errors will be displayed.) * * Revision 1.28 2004/07/15 05:49:22 chessing * * We now reset ALLMULTI to the state is was in when we start XSupplicant. Also, when we have to reset keys, we now reset all of them, instead of just the first one. * * Revision 1.27 2004/07/15 04:15:35 chessing * * True/false int values are now bit flags in a byte. PEAP now calls back in to functions from eap.c for phase 2 methods. This allows for any phase 1 EAP type to work. This resulted in some major changes the functions in eap.c, and in peap_phase2.c. PEAP has been tested using both MS-CHAPv2, and EAP-MD5 as inner types. More types need to be tested, and enabled. * * Revision 1.26 2004/06/21 05:19:12 chessing * * Added a few minor fixes to EAP-AKA support. Added "allmulti" as a global configuration option. (By default, allmulti is now on!) * * Revision 1.25 2004/06/15 03:22:29 chessing * * XSupplicant Release 1.0 * * *******************************************************************/#include <fcntl.h>#include <string.h>#include <sys/ioctl.h>#include <netinet/in.h>#include <linux/wireless.h>#include <linux/if_packet.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include <net/if_arp.h>#include "../config.h"#include "../profile.h"#include "linux/cardif_linux_ssids.h"#include "cardif.h"#include "../xsup_debug.h"#include "../xsup_err.h"#include "linux/cardif_linux.h"#ifndef ETH_P_EAPOL#define ETH_P_EAPOL 0x888e#endif#define SCAN_TIMEOUT 30 // Wait 30 seconds before scanning again.// Define this, so the compiler doesn't complain.extern unsigned int if_nametoindex(const char *);/*********************************************** * * Do whatever is needed to get the interface in to a state that we can send * and recieve frames on the network. Any information that we need to later * use should be stored in the interface_data structure. * ***********************************************/int cardif_init(struct interface_data *thisint){ struct ifreq ifr; struct lin_sock_data *sockData; int sockopts, sockerr, retval; debug_printf(DEBUG_INT, "Initializing socket for interface %s..\n", thisint->intName); // Find out what the interface index is. thisint->intIndex = if_nametoindex(thisint->intName); debug_printf(DEBUG_INT, "Index : %d\n", thisint->intIndex); // Allocate memory for the things we need. thisint->sockData = (void *)malloc(sizeof(struct lin_sock_data)); if (thisint->sockData == NULL) { debug_printf(DEBUG_NORMAL, "Error allocating memory!\n"); return XEMALLOC; } sockData= thisint->sockData; // Amount of time to wait before allowing a scan again. sockData->scan_timer = 0; // Establish a socket handle. sockData->sockInt = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_EAPOL)); if (sockData->sockInt < 0) { debug_printf(DEBUG_NORMAL, "Couldn't initialize raw socket for interface %s!\n", thisint->intName); return XENOSOCK; } // Tell the ifreq struct which interface we want to use. strncpy((char *)&ifr.ifr_name, thisint->intName, sizeof(ifr.ifr_name)); retval = ioctl(sockData->sockInt, SIOCGIFINDEX, &ifr); if (retval < 0) { debug_printf(DEBUG_NORMAL, "Error getting interface index value for interface %s\n", thisint->intName); return XESOCKOP; } // Build our link layer socket struct, so we can bind it to a specific // interface. sockData->sll.sll_family = PF_PACKET; sockData->sll.sll_ifindex = ifr.ifr_ifindex; sockData->sll.sll_protocol = htons(ETH_P_EAPOL); // Bind to the interface. retval = bind(sockData->sockInt, (const struct sockaddr *)&sockData->sll, sizeof(struct sockaddr_ll)); if (retval < 0) { debug_printf(DEBUG_NORMAL, "Error binding raw socket to interface %s!\n", thisint->intName); return XESOCKOP; } // Get our MAC address. (Needed for sending frames out correctly.) retval = ioctl(sockData->sockInt, SIOCGIFHWADDR, &ifr); if (retval < 0) { debug_printf(DEBUG_NORMAL, "Error getting hardware (MAC) address for interface %s!\n", thisint->intName); return XENOTINT; } // Store a copy of our source MAC for later use. memcpy((char *)&thisint->source_mac[0], (char *)&ifr.ifr_hwaddr.sa_data[0], 6); // Check if we want ALLMULTI mode, and enable it. if (config_get_allmulti() == 1) { // Tell the ifreq struct which interface we want to use. strncpy((char *)&ifr.ifr_name, thisint->intName, sizeof(ifr.ifr_name)); if (ioctl(sockData->sockInt, SIOCGIFFLAGS, &ifr) < 0) { debug_printf(DEBUG_NORMAL, "Couldn't determine if ALLMULTI is enabled!\n"); } else { if (ifr.ifr_flags & IFF_ALLMULTI) { debug_printf(DEBUG_INT, "Allmulti mode is already enabled on this device!\n"); thisint->flags |= ALLMULTI; } else { debug_printf(DEBUG_INT, "Allmulti is currently disabled on this device!\n"); thisint->flags &= ~ALLMULTI; } } ifr.ifr_flags |= IFF_ALLMULTI; if (ioctl(sockData->sockInt, SIOCSIFFLAGS, &ifr) < 0) { debug_printf(DEBUG_NORMAL, "Couldn't set ALLMULTI mode on this interface! We will continue anyway!\n"); } } // Set our socket to non-blocking. sockopts = fcntl(sockData->sockInt, F_GETFL, 0); if (sockopts < 0) { debug_printf(DEBUG_NORMAL, "Error getting socket options for interface %s!\n", thisint->intName); return XENOTINT; } sockerr = fcntl(sockData->sockInt, F_SETFL, sockopts | O_NONBLOCK); if (sockerr < 0) { debug_printf(DEBUG_NORMAL, "Error setting socket options for interface %s!\n", thisint->intName); return XENOTINT; } return XENONE;}/**************************************************************** * * This is called each time the internal clock ticks. (Once a second.) * It should be used to update any timers that are to be used inside * of cardif. * ****************************************************************/void cardif_clock_tick(struct interface_data *intdata){ struct lin_sock_data *sockData; sockData= intdata->sockData; if (sockData->scan_timer > 0) { sockData->scan_timer--; }}/************************************************************** * * Check if encryption is available. If it is, we will return * TRUE, if it isn't, we will return FALSE. On error, we return * -1. * **************************************************************/int cardif_enc_enabled(struct interface_data *thisint){ int rc = 0; int skfd; struct iwreq wrq; bzero((struct iwreq *)&wrq, sizeof(struct iwreq)); skfd = socket(AF_INET, SOCK_DGRAM, 0); if (skfd < 0) return -1; strncpy(wrq.ifr_name, thisint->intName, IFNAMSIZ); if ((rc = ioctl(skfd, SIOCGIWENCODE, &wrq)) < 0) { // We got an error while trying to get encryption information // from the card. rc = -1; } else { // We got some data, so see if we have encryption or not. if ((wrq.u.data.flags & IW_ENCODE_DISABLED) == IW_ENCODE_DISABLED) { // Encryption is disabled. rc = FALSE; } else { // Encryption is enabled. rc = TRUE; } } close(skfd); return rc;}/************************************************************** * * Force the card in to open mode. (The call cardif_enc_open will only * set the card to open mode if it has been in the past.) * **************************************************************/int cardif_force_enc_on_open(struct interface_data *thisint){ int rc = 0; char key[5]={0x00,0x00,0x00,0x00,0x00}; struct iwreq wrq; struct lin_sock_data *sockData; if (!(thisint->flags & WEP)) { debug_printf(DEBUG_INT, "WEP not desired!\n"); return XENONE; } sockData = thisint->sockData; bzero((struct iwreq *)&wrq, sizeof(struct iwreq)); strncpy(wrq.ifr_name, thisint->intName, IFNAMSIZ); wrq.u.data.pointer = (caddr_t)&key; wrq.u.data.flags = 0; wrq.u.data.length = 5; if (ioctl(sockData->sockInt, SIOCSIWENCODE, &wrq) < 0) { debug_printf(DEBUG_INT, "Error setting open encoding mode!\n"); rc = -1; } return rc;}/************************************************************** * * If we have detected, or forced this interface to reset keys, then * we need to reset them. Otherwise, we will just ignore the fact that * we changed APs, and return. * **************************************************************/void cardif_reset_keys(struct interface_data *thisint){ char zerokey[13]; char keylen = 13;#ifdef EXPERIMENTAL struct ssids_list *ourssid;#endif if (thisint->userdata == NULL) { debug_printf(DEBUG_INT, "Userdata is NULL!\n"); return; } if (thisint->userdata->wireless_ctrl == CTL_NO) { debug_printf(DEBUG_INT, "Config file has instructed us not to reset the key! Roaming may not work!!!\n"); return; }#ifdef EXPERIMENTAL ourssid = cardif_linux_ssids_find(thisint); if (ourssid == NULL) { // Leave this as a debug INT because it is more informational, and in // the event we have an invalid SSID for a long time the log will fill // up with these messages... Not pretty! debug_printf(DEBUG_INT, "Couldn't find any information about the SSID we are using!\n"); return; } if (!(ourssid->flags & WEP)) { debug_printf(DEBUG_INT, "SSID doesn't appear to use encryption! Ignoring!\n"); return; }#else if (cardif_enc_enabled(thisint) != TRUE) { debug_printf(DEBUG_INT, "Encryption appears to be disabled. We will not reset keys on interface %s!\n", thisint->intName); return; }#endif bzero(&zerokey, 13);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -