├── README.md ├── sguclient-OpenWrt-LuCI ├── root └── sguclient │ ├── Makefile │ ├── i18n │ └── zh-cn │ │ ├── sguclient.zh-cn.lmo │ │ └── sguclient.zh-cn.lo │ ├── luci_files │ └── root │ │ ├── etc │ │ ├── config │ │ │ └── sguclient │ │ └── init.d │ │ │ └── sguclient │ │ └── usr │ │ └── lib │ │ └── lua │ │ └── luci │ │ ├── controller │ │ └── sguclient.lua │ │ └── model │ │ └── cbi │ │ └── sguclient.lua │ └── src │ ├── Makefile │ ├── dprotocol.c │ ├── dprotocol.h │ ├── main.c │ ├── md5.c │ ├── md5.h │ ├── public.c │ ├── public.h │ ├── sguclient.c │ └── sguclient.h └── sguclient-linux ├── Makefile ├── dprotocol.c ├── dprotocol.h ├── main.c ├── md5.c ├── md5.h ├── public.c ├── public.h ├── sguclient ├── sguclient.c └── sguclient.h /README.md: -------------------------------------------------------------------------------- 1 | # 韶关学院校园网第三方拨号器 2 | 3 | 当年年少不懂事,东拼西凑弄的一个小东西,现在毕业了,留给有需要的师弟师妹吧。Have fun anyway! 4 | 5 | ## 关于 6 |         SGUClient是一个纯C系语言编写的**韶关学院**学生宿舍区第三方网络认证拨号器。现在有Ubuntu和OpenWrt二进制文件可用。当然了,得益于C系语言良好的可移植性,你可以获得SGUClient的源代码然后轻松移植到你需要的平台上(Feel free to make changes)。 7 |
        SGUClient内置2套拨号协议,所以在全校、全网应该都可以正常使用。准确来说,兼容电信和移动网络,兼容南区、北区和西区网络,兼容Drcom拨号器和新旧小蝴蝶拨号器。但黄田坝校区和紫藤苑未经实地测试。 8 |
        现在SGUClient也有了LuCI图形化配置页面,所以在OpenWrt路由器上运行SGUClient或许是一个不错的选择。 9 | 10 | ## 严肃警告 11 | - **仅可用于学习目的** 12 | 13 |        SGUClient及其有关资料仅可供韶关学院师生用于学习计算机网络知识、学习计算机编程知识的用途,其他任何用途均为不正常使用。由于不正常使用所导致的一切直接或间接后果及法律责任均由使用者自行承担,SGUClient作者不承担任何责任。 14 | - **禁止用于商业用途** 15 | 16 |        特别指出禁止任何个人或团体将SGUClient或其有关资料用于商业目的。由此造成的后果与法律责任均与开发者、公众号持有者以及QQ群友无关! 17 | - **从未授权任何商业、推广活动** 18 | 19 |        **SGUClient是免费、开源软件,用户无需为其支付任何费用!** 20 | 21 |        SGUClient的开发者从未授权任何形式的商业活动、推广活动,也不提供任何付费服务。一切与SGUClient有关的商业活动、推广活动(包括但不限于`收费代刷路由器`、`收费上门推广安装WiFi`等)均为不正常使用的行为。SGUClient开发者对这些不正常使用的行为不知情、不支持、不鼓励,也不会承担任何责任。你在参与这些不正常使用的行为中付出的代价(例如`跑路`、`金钱损失`、`隐私信息被盗泄露`、`封号`等)均与SGUClient开发者无关! 22 | - **不鼓励用于分享网络** 23 | 24 |        SGUClient的出发点是给韶关学院师生提供一些可供学习研究的编程资料,因此不鼓励利用SGUClient或其有关资料进行分享网络的行为(包括但不限于`开WiFi`、`多人合用一条宽带`等)。与他人分享网络可能是违规行为! 25 | - **抵制商业用途** 26 | 27 |        窃取他人免费、开源的劳动成果用来赚钱是不道德的行为;付费让别人代刷路由器是助纣为虐的行为,更是对自己的隐私安全不负责任的行为。 28 | 29 |        `收费代刷路由器`、`收费上门推广安装WiFi`等高调作死行为只会加速得罪有关利益方,让别人尽快封杀SGUClient。哪天没得研究了就是你们这些人亲手造成的; 30 | 31 |        同时,这些上门代刷的路由器中会不会偷偷安插了木马病毒软件用于`盗号`、`盗取隐私`、`窃取机密资料`等违法犯罪用途,只有代刷路由器的人自己知道,谁都不敢保证。为了你自己的隐私安全,请勿轻信`收费代刷路由器`、`收费上门推广安装WiFi`等服务。 32 | 33 |
34 | 你必须完全阅读、理解并接受以上内容才可以继续使用SGUClient及其相关资料。 35 | 36 | 如果你不明白或不接受以上内容,请勿使用SGUClient,并且立即将SGUClient及其相关资料从你的设备中移除。 37 | 38 | ## 快速上手 39 | * [Ubuntu使用SGUClient](https://github.com/dafeiyoung/sguclient/wiki/Ubuntu%E4%BD%BF%E7%94%A8SGUClient)
40 | * [OpenWrt(路由器)使用SGUClient](https://github.com/dafeiyoung/sguclient/wiki/OpenWrt(%E8%B7%AF%E7%94%B1%E5%99%A8)%E4%BD%BF%E7%94%A8SGUClient)
41 | 42 | ## 编译 43 | * [Ubuntu编译SGUClient](https://github.com/dafeiyoung/sguclient/wiki/Ubuntu%E7%BC%96%E8%AF%91SGUClient)
44 | * [交叉编译SGUClient For OpenWrt](https://github.com/dafeiyoung/sguclient/wiki/%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91SGUClient-For-OpenWrt) 45 | 46 | ## 故障排除 47 | * [故障排除](https://github.com/dafeiyoung/sguclient/wiki/%E6%95%85%E9%9A%9C%E6%8E%92%E9%99%A4) 48 | 49 | ## 版权声明 50 | SGUClient是很久很久之前弄的一个东西了,编写过程中借(chao)鉴(xi)了很多开源项目的源代码。主要有:
51 | * drcom协议部分使用了[fsn_server](https://github.com/YSunLIN/fsn_server)的源代码 52 | * 程序框架使用了ZTE-Client的源代码 53 | * LuCI部分使用了[njit-client](http://www.cnblogs.com/mayswind/p/3468124.html)的LuCI部分源代码 54 |
_历史久远,如果有遗留,请联系我。_ 55 |
感谢以上作者的辛勤付出。侵删。 56 |
57 | 欢迎star,欢迎fork,欢迎pull request,但禁止任何个人或团体将SGUClient用于商业目的,由此造成的后果与法律责任均与开发者、公众号持有者以及QQ群友无关! 58 | 59 | ## 再说几句 60 | a. 历时很多很多年改来改去的一个东西,当年shit一样的代码风格,所以请勿在饭前饭后阅读源代码。 61 |
62 | b. 欢迎加入`QQ群638138948`讨论。韶关学院师生进群请备注“学院-年级-昵称”例如“信工-14-二狗子”,非韶关学院师生进入请备注学校(这只是为了方便统计,希望理解)。 63 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/root: -------------------------------------------------------------------------------- 1 | */1 * * * * sguclient -u 14115678912 -p 111111 -i D --device eth0.2 --ip 192.168.12.34 #sguclient# -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/rules.mk 2 | 3 | PKG_NAME:=sguclient 4 | PKG_VERSION:=0.20 5 | PKG_RELEASE:=r0.20-luci 6 | 7 | PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME) 8 | 9 | include $(INCLUDE_DIR)/package.mk 10 | 11 | define Package/$(PKG_NAME) 12 | SECTION:=utils 13 | CATEGORY:=Utilities 14 | TITLE:=sguclient 15 | MAINTAINER:=young 16 | DEPENDS:=+libpcap +libpthread 17 | endef 18 | 19 | define Package/$(PKG_NAME)/description 20 | sguclient general program 21 | endef 22 | 23 | define Build/Prepare 24 | mkdir -p $(PKG_BUILD_DIR) 25 | $(CP) ./src/* $(PKG_BUILD_DIR)/ 26 | $(foreach po,$(wildcard ${CURDIR}/i18n/zh-cn/*.po), \ 27 | po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));) 28 | endef 29 | 30 | define Package/sguclient/install 31 | $(INSTALL_DIR) $(1)/bin 32 | $(INSTALL_DIR) $(1)/etc/config 33 | $(INSTALL_DIR) $(1)/etc/init.d 34 | $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi 35 | $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller 36 | $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n 37 | 38 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/sguclient $(1)/bin/ 39 | $(INSTALL_CONF) ./luci_files/root/etc/config/sguclient $(1)/etc/config/sguclient 40 | $(INSTALL_BIN) ./luci_files/root/etc/init.d/sguclient $(1)/etc/init.d/sguclient 41 | $(INSTALL_DATA) ./luci_files/root/usr/lib/lua/luci/model/cbi/sguclient.lua $(1)/usr/lib/lua/luci/model/cbi/sguclient.lua 42 | $(INSTALL_DATA) ./luci_files/root/usr/lib/lua/luci/controller/sguclient.lua $(1)/usr/lib/lua/luci/controller/sguclient.lua 43 | $(INSTALL_DATA) ./i18n/zh-cn/*.lmo $(1)/usr/lib/lua/luci/i18n/ 44 | endef 45 | 46 | $(eval $(call BuildPackage,sguclient)) 47 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/i18n/zh-cn/sguclient.zh-cn.lmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dafeiyoung/sguclient/1865e962ab4503b5e0be0591fc7e4807c1864716/sguclient-OpenWrt-LuCI/sguclient/i18n/zh-cn/sguclient.zh-cn.lmo -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/i18n/zh-cn/sguclient.zh-cn.lo: -------------------------------------------------------------------------------- 1 | msgid "ShaoGuan University 3rd Party Network Authentication Client.
QQ Group: 638138948" 2 | msgstr "韶关学院第三方校园网拨号器
QQ群: 638138948" 3 | 4 | msgid "Enable" 5 | msgstr "启用" 6 | 7 | msgid "Auto Reconnect" 8 | msgstr "自动重连" 9 | 10 | msgid "No 1x Heart Beat" 11 | msgstr "不需要802.1x心跳" 12 | 13 | msgid "1x Username" 14 | msgstr "内网(校园网)账号" 15 | 16 | msgid "1x Password" 17 | msgstr "内网(校园网)密码" 18 | 19 | msgid "ISP Type" 20 | msgstr "网络运营商类型" 21 | 22 | msgid "AuthInterface" 23 | msgstr "认证网卡" 24 | 25 | msgid "Wan IP Address" 26 | msgstr "认证网卡的IP地址" 27 | 28 | msgid "Main control of SGUClient" 29 | msgstr "SGUClient总开关" 30 | 31 | msgid "Reconnect if client went off-line(Generally NOT checked)" 32 | msgstr "客户端离线时自动重连(一般不勾选)" 33 | 34 | msgid "No 802.1x heart beat and cancel alarm(Generally NOT checked)" 35 | msgstr "不需802.1x心跳并关闭超时闹钟(新宿舍苑专用, 其他苑一般不勾选)" 36 | 37 | msgid "Fill in your 802.1x username" 38 | msgstr "请填入你的内网账号" 39 | 40 | msgid "Fill in your 802.1x password" 41 | msgstr "请填入你的内网密码" 42 | 43 | msgid "Chose your ISP Type" 44 | msgstr "选择你的实际网络运营商类型" 45 | 46 | msgid "CTCC(DX)" 47 | msgstr "电信" 48 | 49 | msgid "CMCC(YD)" 50 | msgstr "移动" 51 | 52 | msgid "Chose your authentication interface" 53 | msgstr "请选择你的内网认证网卡" 54 | 55 | msgid "Authentication interface IPv4 address(must be the same as which filled in 'Network-Interfaces')" 56 | msgstr "请填写上述认证网卡的实际IPv4地址(务必要和‘网络-接口’里填写的完全一样)" 57 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/luci_files/root/etc/config/sguclient: -------------------------------------------------------------------------------- 1 | config login 2 | option username '' 3 | option password '' -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/luci_files/root/etc/init.d/sguclient: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | START=99 3 | 4 | run_sguclient() 5 | { 6 | local enable 7 | config_get_bool enable $1 enable 8 | 9 | if [ $enable ]; then 10 | local autoreconnect 11 | local username 12 | local password 13 | local isptype 14 | local ifname 15 | local wanip 16 | 17 | config_get_bool autoreconnect $1 autoreconnect 18 | config_get_bool noheartbeat $1 noheartbeat 19 | config_get username $1 username 20 | config_get password $1 password 21 | config_get isptype $1 isptype 22 | config_get ifname $1 ifname 23 | config_get wanip $1 wanip 24 | 25 | while true 26 | do 27 | process=`pgrep sguclient` 28 | 29 | if [ -n "$process" ];then 30 | echo "sguclient is running, ignored..." 31 | else 32 | echo "sguclient not running, trying to start again..." 33 | 34 | #----To start sguclient 35 | if [ $autoreconnect ]; then 36 | if [ $noheartbeat ]; then 37 | sguclient -u $username -p $password -i $isptype --device $ifname --ip $wanip --auto --noheartbeat & 38 | else 39 | sguclient -u $username -p $password -i $isptype --device $ifname --ip $wanip --auto & 40 | fi 41 | else 42 | if [ $noheartbeat ]; then 43 | sguclient -u $username -p $password -i $isptype --device $ifname --ip $wanip --noheartbeat & 44 | else 45 | sguclient -u $username -p $password -i $isptype --device $ifname --ip $wanip & 46 | fi 47 | fi 48 | echo "SGUClient has started." 49 | #---- 50 | 51 | fi 52 | 53 | sleep 60; 54 | 55 | done #end of while 56 | fi 57 | } 58 | 59 | start() 60 | { 61 | config_load sguclient 62 | config_foreach run_sguclient login 63 | } 64 | 65 | stop() 66 | { 67 | killall sguclient 68 | echo "SGUClient has stoped." 69 | } 70 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/luci_files/root/usr/lib/lua/luci/controller/sguclient.lua: -------------------------------------------------------------------------------- 1 | module("luci.controller.sguclient", package.seeall) 2 | 3 | function index() 4 | entry({"admin", "network", "sguclient"}, cbi("sguclient"), _("SGUClient LuCI"), 100) 5 | end -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/luci_files/root/usr/lib/lua/luci/model/cbi/sguclient.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | LuCI - Lua Configuration Interface 3 | 4 | Copyright 2010 Jo-Philipp Wich 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | ]]-- 12 | 13 | require("luci.sys") 14 | 15 | m = Map("sguclient", translate("SGUClient LuCI"), translate("ShaoGuan University 3rd Party Network Authentication Client.
QQ Group: 638138948")) 16 | 17 | s = m:section(TypedSection, "login", "") 18 | s.addremove = false 19 | s.anonymous = true 20 | 21 | enable = s:option(Flag, "enable", translate("Enable"),translate("Main control of SGUClient")) 22 | enable = s:option(Flag, "autoreconnect", translate("Auto Reconnect"),translate("Reconnect if client went off-line(Generally NOT checked)")) 23 | enable = s:option(Flag, "noheartbeat", translate("No 1x Heart Beat"),translate("No 802.1x heart beat and cancel alarm(Generally NOT checked)")) 24 | name = s:option(Value, "username", translate("1x Username"),translate("Fill in your 802.1x username")) 25 | pass = s:option(Value, "password", translate("1x Password"),translate("Fill in your 802.1x password")) 26 | pass.password = true 27 | 28 | isptype=s:option(ListValue,"isptype",translate("ISP Type"),translate("Chose your ISP Type")) 29 | isptype:value("D",translate("CTCC(DX)")) 30 | isptype:value("Y",translate("CMCC(YD)")) 31 | 32 | ifname = s:option(ListValue, "ifname", translate("AuthInterface"),translate("Chose your authentication interface")) 33 | 34 | wanip = s:option(Value, "wanip", translate("Wan IP Address"),translate("Authentication interface IPv4 address(must be the same as which filled in 'Network-Interfaces')")) 35 | wanip.datatype="ip4addr" 36 | 37 | for k, v in ipairs(luci.sys.net.devices()) do 38 | if v ~= "lo" then 39 | ifname:value(v) 40 | end 41 | end 42 | 43 | local apply = luci.http.formvalue("cbi.apply") 44 | if apply then 45 | io.popen("/etc/init.d/sguclient restart") 46 | end 47 | 48 | return m 49 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/Makefile: -------------------------------------------------------------------------------- 1 | OBJECTS=sguclient 2 | 3 | LDFLAGS+=-lpcap -lpthread 4 | 5 | all: $(OBJECTS) 6 | PKG_NAME=docs 7 | 8 | sguclient: main.o md5.o sguclient.o public.o dprotocol.o 9 | $(CC) $(LDFLAGS) $^ -o $@ 10 | sguclient.o:sguclient.c 11 | $(CC) $(CFLAGS) -c $< 12 | main.o:main.c 13 | $(CC) $(CFLAGS) -c $< 14 | md5.o:md5.c 15 | $(CC) $(CFLAGS) -c $< 16 | public.o:public.c 17 | $(CC) $(CFLAGS) -c $< 18 | dprotocol.o:dprotocol.c 19 | $(CC) $(CFLAGS) -c $< 20 | 21 | .PHONY:clean 22 | clean: 23 | @-rm *.o sguclient 24 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/dprotocol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: dprotocol.c 5 | * 6 | * Description: 主要含drcom认证的代码(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "dprotocol.h" 20 | #include "public.h" 21 | 22 | char drcom_challenge[4]; 23 | char drcom_keepalive_info[4]; 24 | char drcom_keepalive_info2[16]; 25 | char drcom_misc1_flux[4]; 26 | char drcom_misc3_flux[4]; 27 | 28 | char revData[RECV_BUF_LEN]; 29 | 30 | 31 | static int sock; 32 | static struct sockaddr_in clientaddr; 33 | static struct sockaddr_in drcomaddr; 34 | 35 | /* 36 | * === FUNCTION ====================================================================== 37 | * Name: drcom_crc32 38 | * Description: 计算drcom协议中的crc校验值 39 | * Input: *data: 指向数据包内容的指针; data_len: 数据包的长度 40 | * Output: 返回计算出来的校验值 41 | * ===================================================================================== 42 | */ 43 | uint32_t drcom_crc32(char *data, int data_len) 44 | { 45 | uint32_t ret = 0; 46 | int i = 0; 47 | for (i = 0; i < data_len;) { 48 | ret ^= *(unsigned int *) (data + i); 49 | ret &= 0xFFFFFFFF; 50 | i += 4; 51 | } 52 | 53 | // 大端小端的坑 54 | if(checkCPULittleEndian() == 0) ret = big2little_32(ret); 55 | ret = (ret * 19680126) & 0xFFFFFFFF; 56 | if(checkCPULittleEndian() == 0) ret = big2little_32(ret); 57 | 58 | return ret; 59 | } 60 | 61 | /* 62 | * === FUNCTION ====================================================================== 63 | * Name: start_request 64 | * Description: 发起drcom协议的认证(发送长度为8的数据包) 65 | * Input: 无 66 | * Output: 成功返回0;失败返回-1 67 | * ===================================================================================== 68 | */ 69 | int start_request() 70 | { 71 | const int pkt_data_len = 8; 72 | char pkt_data[8] = 73 | { 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 }; 74 | 75 | memset(revData, 0, RECV_BUF_LEN); 76 | 77 | int revLen = 78 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 79 | #if DRCOM_DEBUG_ON > 0 80 | print_hex_drcom(revData, revLen); 81 | #endif 82 | 83 | if (revData[0] != 0x07) // Start Response 84 | return -1; 85 | 86 | memcpy(drcom_challenge, revData + 8, 4); // Challenge 87 | 88 | #if DRCOM_DEBUG_ON > 0 89 | print_hex_drcom(drcom_challenge, 4); 90 | #endif 91 | 92 | return 0; 93 | } 94 | 95 | /* 96 | * === FUNCTION ====================================================================== 97 | * Name: send_login_auth 98 | * Description: 发起drcom协议的登录(发送包含用户名、主机名等信息的长度为244的数据包) 99 | * Input: 无 100 | * Output: 成功返回0 101 | * ===================================================================================== 102 | */ 103 | int send_login_auth() 104 | { 105 | const int pkt_data_len = 244; 106 | char pkt_data[pkt_data_len]; 107 | 108 | memset(pkt_data, 0, pkt_data_len); 109 | int data_index = 0; 110 | 111 | int i = 0; 112 | 113 | // header 114 | pkt_data[data_index++] = 0x07; // Code 115 | pkt_data[data_index++] = 0x01; //id 116 | pkt_data[data_index++] = 0xf4; //len(244低位) 117 | pkt_data[data_index++] = 0x00; //len(244高位) 118 | pkt_data[data_index++] = 0x03; //step 第几步 119 | pkt_data[data_index++] = strlen(user_id); //uid len 用户ID长度 120 | 121 | // mac 122 | memcpy(pkt_data + data_index, my_mac, 6); 123 | data_index += 6; 124 | 125 | // ip 126 | memcpy(pkt_data + data_index, &my_ip.sin_addr, 4); 127 | data_index += 4; 128 | 129 | // fix(4B) 130 | pkt_data[data_index++] = 0x02; 131 | pkt_data[data_index++] = 0x22; 132 | pkt_data[data_index++] = 0x00; 133 | pkt_data[data_index++] = 0x28; //changed from 0x2a to 0x28,but I do not know why. 134 | 135 | // challenge 136 | memcpy(pkt_data + data_index, drcom_challenge, 4); 137 | data_index += 4; 138 | 139 | // crc32(后面再填) 140 | pkt_data[data_index++] = 0xc7; 141 | pkt_data[data_index++] = 0x2f; 142 | pkt_data[data_index++] = 0x31; 143 | pkt_data[data_index++] = 0x01; 144 | 145 | // 做完crc32后,在把第一个字节置位0 146 | pkt_data[data_index++] = 0x7e; 147 | pkt_data[data_index++] = 0x00; 148 | pkt_data[data_index++] = 0x00; 149 | pkt_data[data_index++] = 0x00; 150 | 151 | // 0x0020 帐号 + 计算机名 152 | int user_id_length = strlen(user_id); 153 | memcpy(pkt_data + data_index, user_id, user_id_length); 154 | data_index += user_id_length; 155 | char temp[100]; 156 | memset(temp, 0, 100); 157 | strcpy(temp, "PC-"); 158 | strcat(temp, user_id); 159 | memcpy(pkt_data + data_index, temp, 32 - user_id_length); 160 | data_index += (32 - user_id_length); 161 | 162 | //0x0040 dns 1 (114.114.114.114) 163 | data_index += 12; 164 | pkt_data[data_index++] = 0x72; 165 | pkt_data[data_index++] = 0x72; 166 | pkt_data[data_index++] = 0x72; 167 | pkt_data[data_index++] = 0x72; 168 | 169 | //0x0050 170 | data_index += 16; 171 | 172 | //0x0060 173 | pkt_data[data_index++] = 0x94; 174 | data_index += 3; 175 | pkt_data[data_index++] = 0x06; 176 | data_index += 3; 177 | pkt_data[data_index++] = 0x02; 178 | data_index += 3; 179 | pkt_data[data_index++] = 0xf0; 180 | pkt_data[data_index++] = 0x23; 181 | data_index += 2; 182 | 183 | //0x0070 184 | pkt_data[data_index++] = 0x02; 185 | data_index += 2; 186 | 187 | char drcom_ver[12] = 188 | { 0x44, 0x72, 0x43, 0x4f, 0x4d, 0x00, 0xb8, 0x01, 0x28, 0x00, 189 | 0x00, 0x00 }; 190 | memcpy(pkt_data + data_index, drcom_ver, 12); 191 | data_index += 12; 192 | 193 | //0x0080 194 | data_index += 16; 195 | 196 | //0x0090 197 | data_index += 32; 198 | 199 | //0x00b0 200 | data_index += 4; 201 | char hashcode[] = "c0a5fb14fc037f53ce0cd21ef5f136b94e25d3d4"; 202 | memcpy(pkt_data + data_index, hashcode, 40); 203 | data_index += 24; 204 | 205 | memset(revData, 0, RECV_BUF_LEN); 206 | 207 | unsigned int crc = drcom_crc32(pkt_data, pkt_data_len); 208 | #if DRCOM_DEBUG_ON > 0 209 | print_hex_drcom((char *) &crc, 4); 210 | #endif 211 | 212 | memcpy(pkt_data + 24, (char *) &crc, 4); 213 | memcpy(drcom_keepalive_info, (char *) &crc, 4); 214 | // 完成crc32校验,置位0 215 | pkt_data[28] = 0x00; 216 | 217 | #if DRCOM_DEBUG_ON > 0 218 | print_hex_drcom(pkt_data,pkt_data_len); 219 | #endif 220 | 221 | int revLen = 222 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 223 | #if DRCOM_DEBUG_ON > 0 224 | print_hex_drcom(revData, revLen); 225 | #endif 226 | 227 | unsigned char *keepalive_info = revData + 16; 228 | for (i = 0; i < 16; i++) 229 | { 230 | drcom_keepalive_info2[i] = (unsigned char) ((keepalive_info[i] << (i & 0x07)) + (keepalive_info[i] >> (8 - (i & 0x07)))); 231 | } 232 | 233 | #if DRCOM_DEBUG_ON > 0 234 | print_hex_drcom(drcom_keepalive_info2, 16); 235 | #endif 236 | 237 | return 0; 238 | } 239 | 240 | /* 241 | * === FUNCTION ====================================================================== 242 | * Name: send_alive_pkt1 243 | * Description: 发起drcom协议的1类型杂项包(发送长度为40的数据包) 244 | * Input: 无 245 | * Output: 成功返回0 246 | * ===================================================================================== 247 | */ 248 | int send_alive_pkt1() 249 | { 250 | const int pkt_data_len = 40; 251 | char pkt_data[pkt_data_len]; 252 | 253 | memset(pkt_data, 0, pkt_data_len); 254 | int data_index = 0; 255 | pkt_data[data_index++] = 0x07; // Code 256 | pkt_data[data_index++] = drcom_pkt_id; //id 257 | pkt_data[data_index++] = 0x28; //len(40低位) 258 | pkt_data[data_index++] = 0x00; //len(40高位) 259 | pkt_data[data_index++] = 0x0B; // Step 260 | pkt_data[data_index++] = 0x01; 261 | 262 | pkt_data[data_index++] = 0xdc; // Fixed Unknown 263 | pkt_data[data_index++] = 0x02; 264 | 265 | pkt_data[data_index++] = 0x00; //每次加一个数 266 | pkt_data[data_index++] = 0x00; 267 | 268 | memcpy(pkt_data + 16, drcom_misc1_flux, 4); 269 | 270 | memset(revData, 0, RECV_BUF_LEN); 271 | int revLen = 272 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 273 | #if DRCOM_DEBUG_ON > 0 274 | print_hex_drcom(revData, revLen); 275 | #endif 276 | 277 | 278 | if (revData[0] != 0x07 && revData[0] !=0x4d) // Misc 279 | return -1; 280 | 281 | if (revData[5] == 0x06 || revData[0] == 0x4d) // File 282 | { 283 | return send_alive_pkt1(); 284 | } 285 | else 286 | { 287 | drcom_pkt_id++; 288 | 289 | memcpy(&drcom_misc3_flux, revData + 16, 4); 290 | return 0; 291 | } 292 | 293 | } 294 | 295 | /* 296 | * === FUNCTION ====================================================================== 297 | * Name: send_alive_pkt2 298 | * Description: 发起drcom协议的3类型杂项包(发送长度为40的数据包) 299 | * Input: 无 300 | * Output: 成功返回0 301 | * ===================================================================================== 302 | */ 303 | int send_alive_pkt2() 304 | { 305 | const int pkt_data_len = 40; 306 | char pkt_data[pkt_data_len]; 307 | 308 | memset(pkt_data, 0, pkt_data_len); 309 | int data_index = 0; 310 | pkt_data[data_index++] = 0x07; // Code 311 | pkt_data[data_index++] = drcom_pkt_id; 312 | pkt_data[data_index++] = 0x28; //len(40低位) 313 | pkt_data[data_index++] = 0x00; //len(40高位) 314 | 315 | pkt_data[data_index++] = 0x0B; // Step 316 | pkt_data[data_index++] = 0x03; 317 | 318 | pkt_data[data_index++] = 0xdc; // Fixed Unknown 319 | pkt_data[data_index++] = 0x02; 320 | 321 | pkt_data[data_index++] = 0x00; //每次加一个数 322 | pkt_data[data_index++] = 0x00; 323 | 324 | 325 | memcpy(pkt_data + 16, drcom_misc3_flux, 4); 326 | memcpy(pkt_data + 28, &my_ip, 4); 327 | 328 | memset(revData, 0, RECV_BUF_LEN); 329 | int revLen = 330 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 331 | #if DRCOM_DEBUG_ON > 0 332 | print_hex_drcom(revData, revLen); 333 | #endif 334 | 335 | drcom_pkt_id++; 336 | 337 | memcpy(drcom_misc1_flux, revData + 16, 4); 338 | return 0; 339 | 340 | } 341 | 342 | /* 343 | * === FUNCTION ====================================================================== 344 | * Name: send_alive_begin 345 | * Description: 发起drcom协议的心跳包,即“Alive,client to server per 20s”(发送长度为38的数据包) 346 | * Input: 无 347 | * Output: 成功返回0 348 | * ===================================================================================== 349 | */ 350 | int send_alive_begin() //keepalive 351 | { 352 | const int pkt_data_len = 38; 353 | char pkt_data[pkt_data_len]; 354 | memset(pkt_data, 0, pkt_data_len); 355 | int data_index = 0; 356 | 357 | pkt_data[data_index++] = 0xff; // Code 358 | 359 | memcpy(pkt_data + data_index, drcom_keepalive_info, 4); 360 | data_index += 19; 361 | 362 | memcpy(pkt_data + data_index, drcom_keepalive_info2, 16); 363 | data_index += 16; 364 | 365 | memset(revData, 0, RECV_BUF_LEN); 366 | int revLen = 367 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 368 | 369 | return 0; 370 | 371 | } 372 | 373 | /* 374 | * === FUNCTION ====================================================================== 375 | * Name: init_env_d 376 | * Description: 初始化socket 377 | * Input: 无 378 | * Output: 无 379 | * ===================================================================================== 380 | */ 381 | // init socket 382 | void init_env_d() 383 | { 384 | memset(&clientaddr, 0, sizeof(clientaddr)); 385 | clientaddr.sin_family = AF_INET; 386 | clientaddr.sin_port = htons(clientPort); 387 | clientaddr.sin_addr = my_ip.sin_addr; 388 | 389 | memset(&drcomaddr, 0, sizeof(drcomaddr)); 390 | drcomaddr.sin_family = AF_INET; 391 | drcomaddr.sin_port = htons(DR_PORT); 392 | inet_pton(AF_INET, DR_SERVER_IP, &drcomaddr.sin_addr); 393 | 394 | sock = socket(AF_INET, SOCK_DGRAM, 0); 395 | if( -1 == sock) 396 | { 397 | perror("Create drcom socket failed"); 398 | exit(-1); 399 | } 400 | 401 | if( 0 != bind(sock, (struct sockaddr *) &clientaddr, sizeof(clientaddr))) 402 | { 403 | perror("Bind drcom sock failed"); 404 | exit(-1); 405 | } 406 | } 407 | 408 | /* 409 | * === FUNCTION ====================================================================== 410 | * Name: init_dial_env 411 | * Description: 初始化拨号环境 412 | * Input: 无 413 | * Output: 无 414 | * ===================================================================================== 415 | */ 416 | void init_dial_env() 417 | { 418 | /* linklayer broadcast address, used to connect the huawei's exchange */ 419 | //const char dev_dest[ETH_ALEN] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 420 | const char dev_dest[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 421 | 422 | 423 | /* set struct sockaddr_ll for sendto function 424 | sa_ll: global value, in "xprotocol.h" */ 425 | sa_ll.sll_family = PF_PACKET; 426 | sa_ll.sll_protocol = htons(ETH_P_ALL); 427 | sa_ll.sll_ifindex = if_nametoindex(interface_name); 428 | sa_ll.sll_hatype = 0; 429 | sa_ll.sll_pkttype = PACKET_HOST | PACKET_BROADCAST | PACKET_MULTICAST; 430 | memcpy(sa_ll.sll_addr, dev_dest, ETH_ALEN); 431 | 432 | sock = create_ethhdr_sock(ð_header); // eth_header,sock: global value 433 | 434 | } 435 | 436 | /* 437 | * === FUNCTION ====================================================================== 438 | * Name: udp_send_and_rev 439 | * Description: 发送并接收udp协议的数据包 440 | * Input: *send_buf: 指向待发送数据的指针; send_len: 待发送数据的长度; 441 | *recv_buf: 指向接收缓冲区的指针 442 | * Output: 返回接收的长度 443 | * ===================================================================================== 444 | */ 445 | int udp_send_and_rev(char* send_buf, int send_len, char* recv_buf) 446 | { 447 | int nrecv_send, addrlen = sizeof(struct sockaddr_in); 448 | struct sockaddr_in clntaddr; 449 | int try_times = RETRY_TIME; 450 | 451 | while(try_times--){ 452 | nrecv_send = sendto(sock, send_buf, send_len, 0, (struct sockaddr *) &drcomaddr, addrlen); 453 | if(nrecv_send == send_len) break; 454 | } 455 | 456 | try_times = RETRY_TIME; 457 | while(try_times--){ 458 | nrecv_send = recvfrom(sock, recv_buf, RECV_BUF_LEN, 0, 459 | (struct sockaddr*) &clntaddr, &addrlen); 460 | if(nrecv_send > 0 && memcmp(&clntaddr.sin_addr, &drcomaddr.sin_addr, 4) == 0) break; 461 | } 462 | 463 | return nrecv_send; 464 | } 465 | 466 | /* 467 | * === FUNCTION ====================================================================== 468 | * Name: perrorAndSleep 469 | * Description: 打印错误信息并休眠 470 | * Input: *str: 指向待打印字符串的指针 471 | * Output: 无 472 | * ===================================================================================== 473 | */ 474 | static void perrorAndSleep(char* str){ 475 | printf("%s\n", str); 476 | strcpy(dstatusMsg, str); 477 | dstatus = DOFFLINE; 478 | sleep(20); 479 | } 480 | 481 | /* 482 | * === FUNCTION ====================================================================== 483 | * Name: printAll 484 | * Description: 打印错误信息 485 | * Input: *str: 指向待打印字符串的指针 486 | * Output: 无 487 | * ===================================================================================== 488 | */ 489 | static void printAll(char* str){ 490 | printf("drcom %s\n", str); 491 | strcpy(dstatusMsg, str); 492 | } 493 | 494 | /* 495 | * === FUNCTION ====================================================================== 496 | * Name: serve_forever_d 497 | * Description: drcom认证主程序 498 | * Input: *args: 传入的参数指针(并不需要) 499 | * Output: 无 500 | * ===================================================================================== 501 | */ 502 | void* serve_forever_d(void *args) 503 | { 504 | int ret; 505 | 506 | drcom_pkt_id = 0; 507 | dstatus = DOFFLINE; 508 | strcpy(dstatusMsg, "please log on first"); 509 | 510 | int needToSendXStart = 1; 511 | 512 | while(1) 513 | { 514 | sleep(2); 515 | if ( xstatus == XOFFLINE) //802.1x还没有上线 516 | { 517 | continue ; 518 | } 519 | 520 | if ( needToSendXStart ) 521 | { 522 | ret = start_request(); 523 | if(ret != 0) 524 | { 525 | printf("login = start request error\n"); 526 | return NULL; 527 | } 528 | needToSendXStart = 0; 529 | } 530 | 531 | if ( (revData[0] == 0x07) && (revData[2] == 0x10) ) //Misc,Response for alive(or Misc,File) 532 | { 533 | printf("Drcom Got: Misc,Response for alive(or Misc,File)\n"); 534 | if ( dstatus == DOFFLINE ) //drcom协议 还没有上线成功 535 | { 536 | ret = send_login_auth(); 537 | if(ret != 0) 538 | { 539 | printf("login = login error\n"); 540 | continue; 541 | } 542 | } 543 | if ( dstatus == DONLINE ) //drcom协议 已经上线成功 544 | { 545 | sleep(3); 546 | ret = send_alive_pkt1(); 547 | if(ret != 0) 548 | { 549 | printf("login = alive phase 1 error\n"); 550 | continue; 551 | } 552 | } 553 | } 554 | 555 | if ( (revData[0] == 0x07) && (revData[2] == 0x30) ) //Misc,3000 556 | { 557 | printf("Drcom Got: Misc,3000\n"); 558 | dstatus = DONLINE; 559 | printf("@@drcom login successfully!\n"); 560 | ret = send_alive_pkt1(); 561 | if(ret != 0) 562 | { 563 | printf("login = alive phase 1 error\n"); 564 | continue; 565 | } 566 | } 567 | 568 | if ( (revData[0] == 0x07) && (revData[5] == 0x02) ) //Misc Type2 569 | { 570 | printf("Drcom Got: Misc Type2\n"); 571 | ret = send_alive_pkt2(); 572 | if(ret != 0) 573 | { 574 | printf("keep = alive phase 2 error\n"); 575 | continue; 576 | } 577 | } 578 | 579 | if ( (revData[0] == 0x07) && (revData[5] == 0x04) ) //Misc Type4 580 | { 581 | printf("Drcom Got: Misc Type4\n"); 582 | printf("@@drcom keep successfully!\n"); 583 | sleep(8); 584 | ret = send_alive_begin(); 585 | if(ret != 0) 586 | { 587 | printf("keep = begin alive error\n"); 588 | continue; 589 | } 590 | } 591 | } 592 | 593 | close(sock); 594 | return NULL; 595 | } -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/dprotocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: dprotocol.h 5 | * 6 | * Description: dprotocol.c的头文件,主要含drcom认证的代码(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #ifndef __DPROTOCOL_H 20 | #define __DPROTOCOL_H 21 | 22 | #include "public.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define DR_SERVER_IP "192.168.127.129" 39 | #define DR_PORT 61440 40 | #define RECV_BUF_LEN 1500 41 | #define RETRY_TIME 15 42 | 43 | 44 | int drcom_pkt_id; 45 | int dstatus; 46 | char dstatusMsg[256]; 47 | 48 | 49 | void init_dial_env(void); 50 | void init_env_d(); 51 | int udp_send_and_rev(char* send_buf, int send_len, char* recv_buf); 52 | void* serve_forever_d(void *args); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: main.c 5 | * 6 | * Description: sguclient的主文件,包含主函数 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "sguclient.h" 26 | #include "public.h" 27 | #include "dprotocol.h" 28 | 29 | #define LOCKFILE "/var/run/sguclient.pid" /* 锁文件 */ 30 | 31 | #define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 32 | 33 | static void signal_interrupted (int signo); 34 | 35 | extern pcap_t *handle; 36 | extern int exit_flag; 37 | 38 | int lockfile; /* 锁文件的描述字 */ 39 | 40 | /* 41 | * === FUNCTION ====================================================================== 42 | * Name: flock_reg 43 | * Description: sguclient加锁防止重复运行 44 | * Input: 无 45 | * Output: 无 46 | * ===================================================================================== 47 | */ 48 | void flock_reg() 49 | { 50 | char buf[16]; 51 | struct flock fl; 52 | fl.l_start = 0; 53 | fl.l_whence = SEEK_SET; 54 | fl.l_len = 0; 55 | fl.l_type = F_WRLCK; 56 | fl.l_pid = getpid(); 57 | 58 | //阻塞式的加锁 59 | if (fcntl (lockfile, F_SETLKW, &fl) < 0){ 60 | perror ("fcntl_reg"); 61 | exit(1); 62 | } 63 | 64 | //把pid写入锁文件 65 | assert (0 == ftruncate (lockfile, 0) ); 66 | sprintf (buf, "%ld", (long)getpid()); 67 | assert (-1 != write (lockfile, buf, strlen(buf) + 1)); 68 | } 69 | 70 | /* 71 | * === FUNCTION ====================================================================== 72 | * Name: daemon_init 73 | * Description: 准备fork至后台 74 | * Input: 无 75 | * Output: 无 76 | * ===================================================================================== 77 | */ 78 | void daemon_init(void) 79 | { 80 | pid_t pid; 81 | int fd0; 82 | 83 | if ( (pid = fork()) < 0) 84 | perror ("Fork"); 85 | else if (pid != 0) { 86 | fprintf(stdout, "&&Info: SGUClient Forked background with PID: [%d]\n\n", pid); 87 | exit(0); 88 | } 89 | setsid(); /* become session leader */ 90 | assert (0 == chdir("/tmp")); /* change working directory */ 91 | umask(0); /* clear our file mode creation mask */ 92 | flock_reg (); 93 | 94 | fd0 = open ("/dev/null", O_RDWR); 95 | dup2 (fd0, STDIN_FILENO); 96 | dup2 (fd0, STDERR_FILENO); 97 | dup2 (fd0, STDOUT_FILENO); 98 | close (fd0); 99 | } 100 | 101 | /* 102 | * === FUNCTION ====================================================================== 103 | * Name: program_running_check 104 | * Description: 检测是否已经有锁(检测程序是否已经在运行) 105 | * Input: 无 106 | * Output: 若无锁则返回0; 若有锁则返回锁着文件的进程pid 107 | * ===================================================================================== 108 | */ 109 | int program_running_check() 110 | { 111 | struct flock fl; 112 | fl.l_start = 0; 113 | fl.l_whence = SEEK_SET; 114 | fl.l_len = 0; 115 | fl.l_type = F_WRLCK; 116 | 117 | //尝试获得文件锁 118 | if (fcntl (lockfile, F_GETLK, &fl) < 0){ 119 | perror ("fcntl_get"); 120 | exit(1); 121 | } 122 | 123 | if (exit_flag) { 124 | if (fl.l_type != F_UNLCK) { 125 | if ( kill (fl.l_pid, SIGINT) == -1 ) 126 | perror("kill"); 127 | fprintf (stdout, "&&Info: Kill Signal Sent to PID %d.\n", fl.l_pid); 128 | } 129 | else 130 | fprintf (stderr, "&&Info: NO SGUClient Running.\n"); 131 | exit (EXIT_FAILURE); 132 | } 133 | 134 | //没有锁,则给文件加锁,否则返回锁着文件的进程pid 135 | if (fl.l_type == F_UNLCK) { 136 | flock_reg (); 137 | return 0; 138 | } 139 | 140 | return fl.l_pid; 141 | } 142 | 143 | /* 144 | * === FUNCTION ====================================================================== 145 | * Name: signal_interrupted 146 | * Description: 处理Ctrl+C用户取消信号,退出整个程序 147 | * Input: signo: 捕获的信号 148 | * Output: 无 149 | * ===================================================================================== 150 | */ 151 | static void signal_interrupted(int signo) 152 | { 153 | fprintf(stdout,"\n&&Info: USER Interrupted. \n"); 154 | send_eap_packet(EAPOL_LOGOFF); 155 | pcap_breakloop (handle); 156 | } 157 | 158 | /* 159 | * === FUNCTION ====================================================================== 160 | * Name: main 161 | * Description: 主函数 162 | * Input: argc: 传入参数的个数; **argv: 传入参数 163 | * Output: 成功返回1 164 | * ===================================================================================== 165 | */ 166 | int main(int argc, char **argv) 167 | { 168 | 169 | //初始化并解释程序的启动参数 170 | init_arguments (&argc, &argv); 171 | 172 | //打开锁文件 173 | lockfile = open (LOCKFILE, O_RDWR | O_CREAT , LOCKMODE); 174 | if (lockfile < 0){ 175 | perror ("Lockfile"); 176 | exit(1); 177 | } 178 | 179 | //检测程序的副本运行(文件锁) 180 | int ins_pid; 181 | if ( (ins_pid = program_running_check ()) ) { 182 | fprintf(stderr,"@@ERROR: SGUClient Already " 183 | "Running with PID %d\n", ins_pid); 184 | fprintf(stdout, "&&Info: run 'sudo kill %d' before re-running SGUClient'\n\n", ins_pid); 185 | exit(EXIT_FAILURE); 186 | } 187 | 188 | //初始化用户信息 189 | init_info(); 190 | 191 | //初始化设备,打开网卡,获得Mac、IP等信息 192 | init_device(); 193 | 194 | //初始化发送帧的缓冲区 195 | init_frames (); 196 | 197 | signal(SIGINT,signal_interrupted); 198 | signal(SIGTERM,signal_interrupted); 199 | signal(SIGALRM,time_out_handler); //注册超时闹钟,超时则自动调用time_out_handler函数 200 | show_local_info(); 201 | 202 | //Drcom认证入口 203 | DrcomAuthenticationEntry(); 204 | 205 | //发出第一个上线请求报文 206 | send_eap_packet (EAPOL_START); 207 | 208 | //进入回呼循环。以后的动作由回呼函数get_packet驱动, 209 | //直到pcap_break_loop执行,退出程序。 210 | pcap_loop (handle, -2, get_packet, NULL); /* main loop */ 211 | pcap_close (handle); 212 | return 0; 213 | } 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.c is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 41 | either statically or dynamically; added missing #include 42 | in library. 43 | 2002-03-11 lpd Corrected argument list for main(), and added int return 44 | type, in test program and T value program. 45 | 2002-02-21 lpd Added missing #include in test program. 46 | 2000-07-03 lpd Patched to eliminate warnings about "constant is 47 | unsigned in ANSI C, signed in traditional"; made test program 48 | self-checking. 49 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 50 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 51 | 1999-05-03 lpd Original version. 52 | */ 53 | 54 | #include "md5.h" 55 | #include 56 | 57 | #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ 58 | #ifdef ARCH_IS_BIG_ENDIAN 59 | # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) 60 | #else 61 | # define BYTE_ORDER 0 62 | #endif 63 | 64 | #define T_MASK ((md5_word_t)~0) 65 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 66 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 67 | #define T3 0x242070db 68 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 69 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 70 | #define T6 0x4787c62a 71 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 72 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 73 | #define T9 0x698098d8 74 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 75 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 76 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 77 | #define T13 0x6b901122 78 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 79 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 80 | #define T16 0x49b40821 81 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 82 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 83 | #define T19 0x265e5a51 84 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 85 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 86 | #define T22 0x02441453 87 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 88 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 89 | #define T25 0x21e1cde6 90 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 91 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 92 | #define T28 0x455a14ed 93 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 94 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 95 | #define T31 0x676f02d9 96 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 97 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 98 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 99 | #define T35 0x6d9d6122 100 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 101 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 102 | #define T38 0x4bdecfa9 103 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 104 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 105 | #define T41 0x289b7ec6 106 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 107 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 108 | #define T44 0x04881d05 109 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 110 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 111 | #define T47 0x1fa27cf8 112 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 113 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 114 | #define T50 0x432aff97 115 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 116 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 117 | #define T53 0x655b59c3 118 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 119 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 120 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 121 | #define T57 0x6fa87e4f 122 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 123 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 124 | #define T60 0x4e0811a1 125 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 126 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 127 | #define T63 0x2ad7d2bb 128 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 129 | 130 | 131 | static void 132 | md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) 133 | { 134 | md5_word_t 135 | a = pms->abcd[0], b = pms->abcd[1], 136 | c = pms->abcd[2], d = pms->abcd[3]; 137 | md5_word_t t; 138 | #if BYTE_ORDER > 0 139 | /* Define storage only for big-endian CPUs. */ 140 | md5_word_t X[16]; 141 | #else 142 | /* Define storage for little-endian or both types of CPUs. */ 143 | md5_word_t xbuf[16]; 144 | const md5_word_t *X; 145 | #endif 146 | 147 | { 148 | #if BYTE_ORDER == 0 149 | /* 150 | * Determine dynamically whether this is a big-endian or 151 | * little-endian machine, since we can use a more efficient 152 | * algorithm on the latter. 153 | */ 154 | static const int w = 1; 155 | 156 | if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ 157 | #endif 158 | #if BYTE_ORDER <= 0 /* little-endian */ 159 | { 160 | /* 161 | * On little-endian machines, we can process properly aligned 162 | * data without copying it. 163 | */ 164 | if (!((data - (const md5_byte_t *)0) & 3)) { 165 | /* data are properly aligned */ 166 | X = (const md5_word_t *)data; 167 | } else { 168 | /* not aligned */ 169 | memcpy(xbuf, data, 64); 170 | X = xbuf; 171 | } 172 | } 173 | #endif 174 | #if BYTE_ORDER == 0 175 | else /* dynamic big-endian */ 176 | #endif 177 | #if BYTE_ORDER >= 0 /* big-endian */ 178 | { 179 | /* 180 | * On big-endian machines, we must arrange the bytes in the 181 | * right order. 182 | */ 183 | const md5_byte_t *xp = data; 184 | int i; 185 | 186 | # if BYTE_ORDER == 0 187 | X = xbuf; /* (dynamic only) */ 188 | # else 189 | # define xbuf X /* (static only) */ 190 | # endif 191 | for (i = 0; i < 16; ++i, xp += 4) 192 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 193 | } 194 | #endif 195 | } 196 | 197 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 198 | 199 | /* Round 1. */ 200 | /* Let [abcd k s i] denote the operation 201 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 202 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 203 | #define SET(a, b, c, d, k, s, Ti)\ 204 | t = a + F(b,c,d) + X[k] + Ti;\ 205 | a = ROTATE_LEFT(t, s) + b 206 | /* Do the following 16 operations. */ 207 | SET(a, b, c, d, 0, 7, T1); 208 | SET(d, a, b, c, 1, 12, T2); 209 | SET(c, d, a, b, 2, 17, T3); 210 | SET(b, c, d, a, 3, 22, T4); 211 | SET(a, b, c, d, 4, 7, T5); 212 | SET(d, a, b, c, 5, 12, T6); 213 | SET(c, d, a, b, 6, 17, T7); 214 | SET(b, c, d, a, 7, 22, T8); 215 | SET(a, b, c, d, 8, 7, T9); 216 | SET(d, a, b, c, 9, 12, T10); 217 | SET(c, d, a, b, 10, 17, T11); 218 | SET(b, c, d, a, 11, 22, T12); 219 | SET(a, b, c, d, 12, 7, T13); 220 | SET(d, a, b, c, 13, 12, T14); 221 | SET(c, d, a, b, 14, 17, T15); 222 | SET(b, c, d, a, 15, 22, T16); 223 | #undef SET 224 | 225 | /* Round 2. */ 226 | /* Let [abcd k s i] denote the operation 227 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 228 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 229 | #define SET(a, b, c, d, k, s, Ti)\ 230 | t = a + G(b,c,d) + X[k] + Ti;\ 231 | a = ROTATE_LEFT(t, s) + b 232 | /* Do the following 16 operations. */ 233 | SET(a, b, c, d, 1, 5, T17); 234 | SET(d, a, b, c, 6, 9, T18); 235 | SET(c, d, a, b, 11, 14, T19); 236 | SET(b, c, d, a, 0, 20, T20); 237 | SET(a, b, c, d, 5, 5, T21); 238 | SET(d, a, b, c, 10, 9, T22); 239 | SET(c, d, a, b, 15, 14, T23); 240 | SET(b, c, d, a, 4, 20, T24); 241 | SET(a, b, c, d, 9, 5, T25); 242 | SET(d, a, b, c, 14, 9, T26); 243 | SET(c, d, a, b, 3, 14, T27); 244 | SET(b, c, d, a, 8, 20, T28); 245 | SET(a, b, c, d, 13, 5, T29); 246 | SET(d, a, b, c, 2, 9, T30); 247 | SET(c, d, a, b, 7, 14, T31); 248 | SET(b, c, d, a, 12, 20, T32); 249 | #undef SET 250 | 251 | /* Round 3. */ 252 | /* Let [abcd k s t] denote the operation 253 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 254 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 255 | #define SET(a, b, c, d, k, s, Ti)\ 256 | t = a + H(b,c,d) + X[k] + Ti;\ 257 | a = ROTATE_LEFT(t, s) + b 258 | /* Do the following 16 operations. */ 259 | SET(a, b, c, d, 5, 4, T33); 260 | SET(d, a, b, c, 8, 11, T34); 261 | SET(c, d, a, b, 11, 16, T35); 262 | SET(b, c, d, a, 14, 23, T36); 263 | SET(a, b, c, d, 1, 4, T37); 264 | SET(d, a, b, c, 4, 11, T38); 265 | SET(c, d, a, b, 7, 16, T39); 266 | SET(b, c, d, a, 10, 23, T40); 267 | SET(a, b, c, d, 13, 4, T41); 268 | SET(d, a, b, c, 0, 11, T42); 269 | SET(c, d, a, b, 3, 16, T43); 270 | SET(b, c, d, a, 6, 23, T44); 271 | SET(a, b, c, d, 9, 4, T45); 272 | SET(d, a, b, c, 12, 11, T46); 273 | SET(c, d, a, b, 15, 16, T47); 274 | SET(b, c, d, a, 2, 23, T48); 275 | #undef SET 276 | 277 | /* Round 4. */ 278 | /* Let [abcd k s t] denote the operation 279 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 280 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) 281 | #define SET(a, b, c, d, k, s, Ti)\ 282 | t = a + I(b,c,d) + X[k] + Ti;\ 283 | a = ROTATE_LEFT(t, s) + b 284 | /* Do the following 16 operations. */ 285 | SET(a, b, c, d, 0, 6, T49); 286 | SET(d, a, b, c, 7, 10, T50); 287 | SET(c, d, a, b, 14, 15, T51); 288 | SET(b, c, d, a, 5, 21, T52); 289 | SET(a, b, c, d, 12, 6, T53); 290 | SET(d, a, b, c, 3, 10, T54); 291 | SET(c, d, a, b, 10, 15, T55); 292 | SET(b, c, d, a, 1, 21, T56); 293 | SET(a, b, c, d, 8, 6, T57); 294 | SET(d, a, b, c, 15, 10, T58); 295 | SET(c, d, a, b, 6, 15, T59); 296 | SET(b, c, d, a, 13, 21, T60); 297 | SET(a, b, c, d, 4, 6, T61); 298 | SET(d, a, b, c, 11, 10, T62); 299 | SET(c, d, a, b, 2, 15, T63); 300 | SET(b, c, d, a, 9, 21, T64); 301 | #undef SET 302 | 303 | /* Then perform the following additions. (That is increment each 304 | of the four registers by the value it had before this block 305 | was started.) */ 306 | pms->abcd[0] += a; 307 | pms->abcd[1] += b; 308 | pms->abcd[2] += c; 309 | pms->abcd[3] += d; 310 | } 311 | 312 | void 313 | md5_init(md5_state_t *pms) 314 | { 315 | pms->count[0] = pms->count[1] = 0; 316 | pms->abcd[0] = 0x67452301; 317 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 318 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 319 | pms->abcd[3] = 0x10325476; 320 | } 321 | 322 | void 323 | md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) 324 | { 325 | const md5_byte_t *p = data; 326 | int left = nbytes; 327 | int offset = (pms->count[0] >> 3) & 63; 328 | md5_word_t nbits = (md5_word_t)(nbytes << 3); 329 | 330 | if (nbytes <= 0) 331 | return; 332 | 333 | /* Update the message length. */ 334 | pms->count[1] += nbytes >> 29; 335 | pms->count[0] += nbits; 336 | if (pms->count[0] < nbits) 337 | pms->count[1]++; 338 | 339 | /* Process an initial partial block. */ 340 | if (offset) { 341 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 342 | 343 | memcpy(pms->buf + offset, p, copy); 344 | if (offset + copy < 64) 345 | return; 346 | p += copy; 347 | left -= copy; 348 | md5_process(pms, pms->buf); 349 | } 350 | 351 | /* Process full blocks. */ 352 | for (; left >= 64; p += 64, left -= 64) 353 | md5_process(pms, p); 354 | 355 | /* Process a final partial block. */ 356 | if (left) 357 | memcpy(pms->buf, p, left); 358 | } 359 | 360 | void 361 | md5_finish(md5_state_t *pms, md5_byte_t digest[16]) 362 | { 363 | static const md5_byte_t pad[64] = { 364 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 365 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 366 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 367 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 368 | }; 369 | md5_byte_t data[8]; 370 | int i; 371 | 372 | /* Save the length before padding. */ 373 | for (i = 0; i < 8; ++i) 374 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 375 | /* Pad to 56 bytes mod 64. */ 376 | md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 377 | /* Append the length. */ 378 | md5_append(pms, data, 8); 379 | for (i = 0; i < 16; ++i) 380 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 381 | } 382 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/public.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: public.c 5 | * 6 | * Description: 定义一些公有的变量和函数,主要供drcom认证使用(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "public.h" 20 | #include 21 | #include 22 | #include 23 | 24 | char EAP_TYPE_ID_SALT[9] = {0x00, 0x44, 0x61, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}; 25 | char EAP_TYPE_MD5_SALT[9] = {0x00, 0x44, 0x61, 0x2a, 0x00, 0xff, 0xff, 0xff, 0xff}; 26 | 27 | /* 28 | * === FUNCTION ====================================================================== 29 | * Name: print_mac 30 | * Description: 以一定格式打印MAC地址 31 | * Input: *src: 待打印的字符串的指针 32 | * Output: 无 33 | * ===================================================================================== 34 | */ 35 | void print_mac(char *src) 36 | { 37 | char mac[32] = ""; 38 | sprintf(mac, "%02x%02x%02x%02x%02x%02x", 39 | (unsigned char)src[0], 40 | (unsigned char)src[1], 41 | (unsigned char)src[2], 42 | (unsigned char)src[3], 43 | (unsigned char)src[4], 44 | (unsigned char)src[5]); 45 | 46 | printf("%s\n", mac); 47 | } 48 | 49 | /* 50 | * === FUNCTION ====================================================================== 51 | * Name: print_hex_drcom 52 | * Description: 打印十六进制字节流 53 | * Input: *hex: 待打印的内容的指针; len: 打印长度 54 | * Output: 无 55 | * ===================================================================================== 56 | */ 57 | #if DRCOM_DEBUG_ON > 0 58 | void print_hex_drcom(char *hex, int len) 59 | { 60 | int i; 61 | for(i=0; i>24) | 97 | (((uint32_t)(A) & 0x00ff0000) >> 8) | 98 | (((uint32_t)(A) & 0x0000ff00) << 8) | 99 | (((uint32_t)(A) & 0x000000ff) << 24)); 100 | } 101 | 102 | // create socket and get src ether address 103 | int crt_sock(struct ifreq * ifr) 104 | { 105 | int s; 106 | int err; 107 | s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); 108 | 109 | /* 110 | assert the ifr->ifr_ifrn.ifrn_name was known before 111 | interface_name was set in get_from_file(), and saved in /etc/8021.config file 112 | */ 113 | memset(ifr, 0, sizeof(struct ifreq)); 114 | strncpy(ifr->ifr_ifrn.ifrn_name, interface_name, sizeof(ifr->ifr_ifrn.ifrn_name)); // interface_name: global value, in public.h 115 | 116 | /* get ip address */ 117 | err = ioctl(s, SIOCGIFADDR, ifr); 118 | if( err < 0) 119 | { 120 | perror("ioctl get ip addr error"); 121 | close(s); 122 | return -1; 123 | } 124 | memcpy(&my_ip, &(ifr->ifr_addr), sizeof(my_ip)); 125 | 126 | /* get hardware address */ 127 | err = ioctl(s, SIOCGIFHWADDR, ifr); 128 | if( err < 0) 129 | { 130 | perror("ioctl get hw_addr error"); 131 | close(s); 132 | return -1; 133 | } 134 | 135 | // refer to: http://blog.chinaunix.net/uid-8048969-id-3417143.html 136 | err = ioctl(s, SIOCGIFFLAGS, ifr); 137 | if( err < 0) 138 | { 139 | perror("ioctl get if_flag error"); 140 | close(s); 141 | return -1; 142 | } 143 | 144 | 145 | // check the if's xstatus 146 | if(ifr->ifr_ifru.ifru_flags & IFF_RUNNING ) 147 | { 148 | printf("eth link up\n"); 149 | } 150 | else 151 | { 152 | printf("eth link down, please check the eth is ok\n"); 153 | return -1; 154 | } 155 | 156 | ifr->ifr_ifru.ifru_flags |= IFF_PROMISC; 157 | err = ioctl(s, SIOCSIFFLAGS, ifr); 158 | if( err < 0) 159 | { 160 | perror("ioctl set if_flag error"); 161 | close(s); 162 | return -1; 163 | } 164 | 165 | return s; 166 | } 167 | 168 | // the dial route all uses the same fixed eth_header and the same sock 169 | int create_ethhdr_sock(struct ethhdr * eth_header) 170 | { 171 | /* mac broadcast address, huawei's exchange */ 172 | //const char dev_dest[ETH_ALEN] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 173 | const char dev_dest[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 174 | 175 | /* acquire interface's id and hardaddress based in struct ifreq and mysock*/ 176 | struct ifreq *myifr; 177 | myifr = (struct ifreq *) malloc( sizeof(struct ifreq) ); 178 | if( NULL == myifr ) 179 | { 180 | perror("Malloc for ifreq struct failed"); 181 | exit(-1); 182 | } 183 | 184 | int mysock; 185 | mysock = crt_sock(myifr); 186 | if(-1 == mysock) 187 | { 188 | perror("Create socket failed"); 189 | exit(-1); 190 | } 191 | 192 | /* create eth header 193 | #define ETH_HLEN 14 */ 194 | memcpy(eth_header->h_dest, dev_dest, ETH_ALEN); 195 | memcpy(eth_header->h_source, myifr->ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN); 196 | memcpy(my_mac, myifr->ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN); 197 | eth_header->h_proto = htons(ETH_P_PAE); // ETH_P_PAE = 0x888e 198 | 199 | // init response salts 200 | //printf("Drcom host ip: %s\n", inet_ntoa(my_ip.sin_addr)); 201 | memcpy(EAP_TYPE_ID_SALT + sizeof(EAP_TYPE_ID_SALT) - 4, &(my_ip.sin_addr), 4); 202 | memcpy(EAP_TYPE_MD5_SALT + sizeof(EAP_TYPE_ID_SALT) - 4, &(my_ip.sin_addr), 4); 203 | 204 | free(myifr); 205 | return mysock; 206 | } 207 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/public.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: public.h 5 | * 6 | * Description: public.c的头文件(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #ifndef __PUBLIC_H_ 20 | #define __PUBLIC_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define DOFFLINE 0 35 | #define DONLINE 1 36 | //-- 37 | #define XOFFLINE 0 38 | #define XONLINE 1 39 | 40 | #define DRCOM_DEBUG_ON 0 //Drcom认证部分的调试开关,置1时输出有关调试信息 41 | 42 | int xstatus; //802.1x状态 43 | struct sockaddr_ll sa_ll; 44 | struct ethhdr eth_header; 45 | char nodifyMsg[256]; 46 | 47 | 48 | char user_id[32]; 49 | char passwd[32]; 50 | char interface_name[32]; 51 | char listen_ip[32]; 52 | int listen_port; 53 | 54 | unsigned int clientPort; 55 | 56 | struct sockaddr_in my_ip; 57 | char my_mac[ETH_ALEN]; 58 | 59 | 60 | void print_mac(char *src); 61 | #if DRCOM_DEBUG_ON > 0 62 | void print_hex_drcom(char *hex, int len); 63 | #endif 64 | int checkCPULittleEndian(); 65 | uint32_t big2little_32(uint32_t A); 66 | int create_ethhdr_sock(struct ethhdr * eth_header); 67 | int crt_sock(struct ifreq * ifr); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /sguclient-OpenWrt-LuCI/sguclient/src/sguclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: sguclient.c 5 | * 6 | * Description: sguclient的主文件,主要包含802.1x认证部分的代码 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "sguclient.h" 20 | 21 | //#include 22 | 23 | #ifndef __linux 24 | static int bsd_get_mac(const char ifname[], uint8_t eth_addr[]); 25 | #endif 26 | 27 | /* ##### GLOBLE VAR DEFINITIONS ######################### */ 28 | /*----------------------------------------------------------------------------- 29 | * 程序的主控制变量 30 | *-----------------------------------------------------------------------------*/ 31 | char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ 32 | pcap_t *handle; /* packet capture handle */ 33 | uint8_t muticast_mac[] = /* 电信802.1x的认证服务器多播地址 */ 34 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 35 | //电信有些苑亦可用01-d0-f8-00-00-03 36 | //注意电信不可用01-80-c2-00-00-03(交换机不识别,收不到回应) 37 | 38 | uint8_t muticast_mac_YD[] = /* 移动802.1x的认证服务器多播地址 */ 39 | {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 40 | //注意:移动多播地址若改为0xff广播,会增强稳定性, 41 | //但紫竹苑将完全无法使用(交换机不识别,收不到回应) 42 | 43 | 44 | /* ##### GLOBLE VAR DEFINITIONS ################### 45 | *----------------------------------------------------------------------------- 46 | * 用户信息的赋值变量,由init_argument函数初始化 47 | *-----------------------------------------------------------------------------*/ 48 | int dhcp_on = 0; /* DHCP 模式标记 */ 49 | int background = 0; /* 后台运行标记 */ 50 | char isp_type='D'; /* 运营商类型,默认是电信(西区) D电信 Y移动 */ 51 | char *dev = NULL; /* 连接的设备名 */ 52 | char *username = NULL; 53 | char *password = NULL; 54 | char *user_gateway = NULL; /* 由用户设定的四个报文参数 */ 55 | char *user_dns = NULL; 56 | char *user_ip = NULL; 57 | char *user_mask = NULL; 58 | int exit_flag = 0; 59 | int auto_rec = 0; /* 断线重拨 */ 60 | int timeout_alarm_1x = 1; 61 | int reconnect_times = 0; /* 超时重连次数 */ 62 | 63 | /* ##### GLOBLE VAR DEFINITIONS ######################### 64 | *----------------------------------------------------------------------------- 65 | * 报文相关信息变量,由init_info 、init_device函数初始化。 66 | *-----------------------------------------------------------------------------*/ 67 | char dev_if_name[64]; 68 | size_t username_length; 69 | size_t password_length; 70 | uint32_t local_ip; /* 网卡IP,网络序,下同 */ 71 | uint32_t local_mask; /* subnet mask */ 72 | uint32_t local_gateway = -1; 73 | uint32_t local_dns = -1; 74 | uint8_t local_mac[ETHER_ADDR_LEN]; /* MAC地址 */ 75 | 76 | 77 | /* ##### TYPE DEFINITIONS ######################### */ 78 | /*----------------------------------------------------------------------------- 79 | * 报文缓冲区,由init_frame函数初始化。 80 | *-----------------------------------------------------------------------------*/ 81 | u_char eapol_start[96]; /* 电信EAPOL START报文 */ 82 | u_char eapol_logoff[96]; /* 电信EAPOL LogOff报文 */ 83 | u_char eapol_keepalive[96]; 84 | u_char eap_response_ident[96]; /* 电信EAP RESPON/IDENTITY报文 */ 85 | u_char eap_response_md5ch[96]; /* 电信EAP RESPON/MD5 报文 */ 86 | 87 | u_char eapol_start_YD[60]; /* 移动EAPOL START报文 */ 88 | u_char eapol_logoff_YD[60]; /* 移动EAPOL LogOff报文 */ 89 | u_char eapol_keepalive_YD[60]; 90 | u_char eap_response_ident_YD[60]; /* 移动EAP RESPON/IDENTITY报文 */ 91 | u_char eap_response_md5ch_YD[60]; /* 移动EAP RESPON/MD5 报文 */ 92 | 93 | uint8_t global_id = 1; //EAP/EAPOL数据包的ID号,不能改为0,否则无法认证 94 | 95 | /* 96 | * === FUNCTION ====================================================================== 97 | * Name: printNotification 98 | * Description: 打印802.1x的notification信息 99 | * Input: * eap_header: 指向EAP/EAPOL数据包的结构体的指针 100 | * Output: 无 101 | * ===================================================================================== 102 | */ 103 | void printNotification(const struct eap_header *eap_header) 104 | { 105 | char *buf = (char *)eap_header; //拷贝一份EAP/EAPOL数据包供打印 106 | int i = 0; 107 | printf("\033[40;31m&&Got notification: \033[1m"); 108 | for (i = 0; i < 46; ++i) //准备打印整个EAP/EAPOL数据包 109 | { 110 | if ( (*buf >= 32) && (*buf <= 127) ) //printable 111 | { 112 | printf("%c", *buf); 113 | } 114 | buf ++; 115 | } 116 | printf("\033[40;31m\033[0m"); //end all special features 117 | printf("\n"); 118 | } 119 | 120 | /* 121 | * === FUNCTION ====================================================================== 122 | * Name: generateRandomPort 123 | * Description: 产生随机UDP端口号 124 | * Input: 无 125 | * Output: 返回产生的随机UDP端口号 126 | * ===================================================================================== 127 | */ 128 | unsigned int generateRandomPort() 129 | { 130 | unsigned int random; 131 | srand((unsigned int)time(0)); 132 | random = 10000 + rand() % 55535; 133 | return random; 134 | } 135 | 136 | /* 137 | * === FUNCTION ====================================================================== 138 | * Name: print_hex 139 | * Description: 打印十六进制字节流 140 | * Input: *array: 指向待打印内容的指针; count: 打印长度 141 | * Output: 无 142 | * ===================================================================================== 143 | */ 144 | void print_hex(uint8_t *array, int count) 145 | { 146 | int i; 147 | for(i = 0; i < count; i++){ 148 | if ( !(i % 16)) 149 | printf ("\n"); 150 | printf("%02x ", array[i]); 151 | } 152 | printf("\n"); 153 | } 154 | 155 | /* 156 | * === FUNCTION ====================================================================== 157 | * Name: DrcomAuthenticationEntry 158 | * Description: drcom认证入口 159 | * Input: 无 160 | * Output: 无 161 | * ===================================================================================== 162 | */ 163 | void DrcomAuthenticationEntry() 164 | { 165 | 166 | if (isp_type == 'D') 167 | { 168 | 169 | pthread_t dtid; //drcom线程的pid 170 | int ret; 171 | 172 | /* 173 | user_id:drcom udp协议用户名(同802.1x) 174 | passwd:drcom udp协议密码(同802.1x) 175 | interface_name:drcom udp协议认证使用的网卡设备名(同802.1x) 176 | */ 177 | strcpy(user_id,username); 178 | strcpy(passwd,password); 179 | strcpy(interface_name,dev); 180 | 181 | // init ip mac and socks 182 | init_dial_env(); 183 | init_env_d(); 184 | 185 | ret = pthread_create(&dtid, NULL, serve_forever_d, NULL); 186 | if( 0 != ret) 187 | { 188 | perror("Create Drcom Thread Failed!"); 189 | exit(EXIT_FAILURE); 190 | } 191 | else printf("Creat Drcom Thread Successfully.\n"); 192 | } 193 | else return; 194 | } 195 | 196 | /* 197 | * === FUNCTION ====================================================================== 198 | * Name: auto_reconnect 199 | * Description: 802.1x睡眠一段时间后重新发起连接的处理函数 200 | * Input: sleep_time_sec: 睡眠时间(秒) 201 | * Output: 无 202 | * ===================================================================================== 203 | */ 204 | void auto_reconnect(int sleep_time_sec) 205 | { 206 | //重新初始化一些变量 207 | global_id = 1; 208 | sleep(sleep_time_sec); 209 | send_eap_packet(EAPOL_START); 210 | } 211 | 212 | /* 213 | * === FUNCTION ====================================================================== 214 | * Name: time_out_handler 215 | * Description: 802.1x等待回应的闹钟超时处理函数 216 | * Input: 无 217 | * Output: 无 218 | * ===================================================================================== 219 | */ 220 | void time_out_handler() 221 | { 222 | printf("SGUClient wait package response time out! \nCheck your physical network connection!\n"); 223 | if ( reconnect_times >= 5 ) //重连次数超过5次 224 | { 225 | printf("SGUClient tried reconnect more than 5 times, but all failed.\n"); 226 | printf("SGUClient exits now!\n"); 227 | exit(EXIT_FAILURE); 228 | } 229 | 230 | if ( auto_rec == 1 ) 231 | { 232 | printf("Try auto reconnect in 5 secs...\n"); 233 | reconnect_times++; 234 | auto_reconnect(5); 235 | } 236 | else 237 | { 238 | printf("Auto reconnection disabled by user,SGUClient exits now!\n"); 239 | exit(EXIT_FAILURE); 240 | } 241 | } 242 | 243 | /* 244 | * === FUNCTION ====================================================================== 245 | * Name: show_usage 246 | * Description: 显示sguclient帮助信息 247 | * Input: 无 248 | * Output: 无 249 | * ===================================================================================== 250 | */ 251 | void show_usage() 252 | { 253 | printf( "\n" 254 | "SGUClient %s \n" 255 | "\t -- Supllicant for ShaoGuan University 802.1x Authentication.\n" 256 | "\t -- A client can be used on the whole campus.\n" 257 | "\t Drcom UDP protocol authentication included(Drcom 5.1.1 X,U62.R110908).\n" 258 | "\n" 259 | " Usage:\n" 260 | "\tRun under root privilege, usually by `sudo', with your \n" 261 | "\taccount info in arguments:\n\n" 262 | "\t-u, --username 802.1x username.\n" 263 | "\t-p, --password 802.1x password.\n" 264 | "\n" 265 | " Optional Arguments:\n\n" 266 | "\t--auto Enable auto reconnect. Default is disabled.\n" 267 | "\t Generally NO NEEDED!\n\n" 268 | "\t--device Specify which device to use.\n" 269 | "\t Default is usually eth0.\n\n" 270 | 271 | "\t--random Use random UDP client port during Drcom authentication.\n" 272 | "\t Sguclient will generate a random client port to replace 61440.\n" 273 | "\t Only effect the client. Server port will not be affected.\n\n" 274 | "\t--noheartbeat Disable timeout alarm clock when waiting for next 802.1x package.\n" 275 | "\t Timeout should be disabled if there is NO 802.1x heart beat package.\n\n" 276 | 277 | "\t--ip Specify your IPv4 address.\n" 278 | "\t It only takes effect when sguclient can not correctly get IP address.\n\n" 279 | 280 | "\t-b, --background Program fork to background after authentication.\n\n" 281 | 282 | "\t-i, --isp_type Specify your ISP type.\n" 283 | "\t 'D' for China Telecom(CTCC), 'Y' for China Mobile(CMCC).\n" 284 | "\t Default is D (China Telecom).\n\n" 285 | "\t-l Tell the process to Logoff.\n\n" 286 | 287 | "\t-h, --help Show this help.\n\n" 288 | "\n" 289 | " About SGUClient:\n\n" 290 | "\tThis program is a C implementation to ShaoGuan University 802.1x Authentication.\n" 291 | "\tBased on other open-source 802.1x programs,SGUClient has simple goal of replacing \n" 292 | "\tthe official clients with ONE client. \n\n" 293 | "\tWarning: This program may not be used for commercial purposes.\n\n" 294 | 295 | "\tSGUClient is a software developed individually, with NO any rela-\n" 296 | "\tiontship with ShaoGuan University or any other company.\n\n\n" 297 | 298 | "\tBug Report? Please join our QQ group: 638138948\n" 299 | "\t\t\t\t\t\t\t\t2015-09-13\n", 300 | SGU_VER); 301 | } 302 | 303 | 304 | /* 305 | * === FUNCTION ====================================================================== 306 | * Name: get_md5_digest 307 | * Description: calcuate for md5 digest 308 | * ===================================================================================== 309 | */ 310 | char* get_md5_digest(const char* str, size_t len) 311 | { 312 | static md5_byte_t digest[16]; 313 | md5_state_t state; 314 | md5_init(&state); 315 | md5_append(&state, (const md5_byte_t *)str, len); 316 | md5_finish(&state, digest); 317 | 318 | return (char*)digest; 319 | } 320 | 321 | /* 322 | * === FUNCTION ====================================================================== 323 | * Name: show_usage 324 | * Description: 根据报文的动作位返回enum EAPType内定义的报文类型 325 | * Input: *eap_header: 指向EAP\EAPOL报文结构体的指针 326 | * Output: 无 327 | * ===================================================================================== 328 | */ 329 | enum EAPType get_eap_type(const struct eap_header *eap_header) 330 | { 331 | switch (eap_header->eap_t) 332 | { 333 | case 0x01: 334 | if ( eap_header->eap_op == 0x01 ) 335 | return EAP_REQUEST_IDENTITY; 336 | if ( eap_header->eap_op == 0x04 ) 337 | return EAP_REQUETS_MD5_CHALLENGE; 338 | if ( eap_header->eap_op == 0xfa ) 339 | return EAP_REQUEST_MD5_KEEP_ALIVE; 340 | if ( eap_header->eap_op == 0x02 ) //802.1x Notification 341 | return EAP_NOTIFICATION; 342 | break; 343 | 344 | case 0x03: 345 | return EAP_SUCCESS; 346 | break; 347 | 348 | case 0x04: 349 | return EAP_FAILURE; 350 | } 351 | 352 | fprintf (stderr, "&&IMPORTANT: Unknown Package : eap_t: %02x\n" 353 | " eap_id: %02x\n" 354 | " eap_op: %02x\n", 355 | eap_header->eap_t, eap_header->eap_id, 356 | eap_header->eap_op); 357 | exit(EXIT_FAILURE); 358 | return ERROR; 359 | } 360 | 361 | 362 | /* 363 | * === FUNCTION ====================================================================== 364 | * Name: action_by_eap_type 365 | * Description: 根据eap报文的类型完成相关的应答 366 | * ===================================================================================== 367 | */ 368 | void action_by_eap_type(enum EAPType pType, 369 | const struct eap_header *header, 370 | const struct pcap_pkthdr *packetinfo, 371 | const uint8_t *packet) 372 | { 373 | if(isp_type=='D') //电信部分 374 | { 375 | printf("Received PackType: %d\n", pType); 376 | switch(pType) 377 | { 378 | case EAP_SUCCESS: 379 | alarm(0); //取消闹钟 380 | xstatus=XONLINE; 381 | fprintf(stdout, ">>Protocol: EAP_SUCCESS\n"); 382 | fprintf(stdout, "&&Info: 802.1x Authorized Access to Network. \n"); 383 | fprintf(stdout, " Then please use PPPOE manually to connect to Internet. \n"); 384 | //print_server_info (packet, packetinfo->caplen); 385 | if ( background ) 386 | { 387 | background = 0; /* 防止以后误触发 */ 388 | daemon_init(); 389 | } 390 | break; 391 | 392 | case EAP_FAILURE: 393 | alarm(0); //取消闹钟 394 | xstatus=XOFFLINE; 395 | fprintf(stdout, ">>Protocol: EAP_FAILURE\n"); 396 | if( auto_rec ) 397 | { 398 | fprintf(stdout, "&&Info: Authentication Failed, auto reconnect in a few sec...\n"); 399 | auto_reconnect(3); //重连,传入睡眠时间 400 | } 401 | else 402 | { 403 | fprintf(stdout, "&&Info: Authentication Failed!\n"); 404 | pcap_breakloop (handle); 405 | } 406 | break; 407 | 408 | case EAP_REQUEST_IDENTITY: 409 | alarm(0); //取消闹钟 410 | fprintf(stdout, ">>Protocol: REQUEST EAP-Identity\n"); 411 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 412 | global_id=header->eap_id; 413 | init_frames(); 414 | send_eap_packet(EAP_RESPONSE_IDENTITY); 415 | break; 416 | 417 | case EAP_REQUETS_MD5_CHALLENGE: 418 | alarm(0); //取消闹钟 419 | fprintf(stdout, ">>Protocol: REQUEST MD5-Challenge(PASSWORD)\n"); 420 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 421 | global_id=header->eap_id; 422 | init_frames(); 423 | fill_password_md5( (uint8_t*)header->eap_md5_challenge, header->eap_id ); 424 | send_eap_packet(EAP_RESPONSE_MD5_CHALLENGE); 425 | break; 426 | 427 | case EAP_REQUEST_IDENTITY_KEEP_ALIVE: 428 | alarm(0); //取消闹钟 429 | fprintf(stdout, ">>Protocol: REQUEST EAP_REQUEST_IDENTITY_KEEP_ALIVE\n"); 430 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 431 | global_id=header->eap_id; 432 | init_frames(); 433 | send_eap_packet(EAP_RESPONSE_IDENTITY_KEEP_ALIVE); 434 | break; 435 | 436 | case EAP_REQUEST_MD5_KEEP_ALIVE: 437 | break; 438 | 439 | case EAP_NOTIFICATION: 440 | printNotification(header); 441 | exit(EXIT_FAILURE); 442 | break; 443 | default: 444 | return; 445 | } 446 | } 447 | 448 | else if(isp_type=='Y') //移动部分 449 | { 450 | printf("Received PackType: %d\n", pType); 451 | switch(pType) 452 | { 453 | case EAP_SUCCESS: 454 | alarm(0); //取消闹钟 455 | fprintf(stdout, ">>Protocol: EAP_SUCCESS\n"); 456 | fprintf(stdout, "&&Info: 802.1x Authorized Access to Network. \n"); 457 | fprintf(stdout, " Then please use PPPOE manually to connect to Internet. \n"); 458 | if (background) 459 | { 460 | background = 0; /* 防止以后误触发 */ 461 | daemon_init (); /* fork至后台,主程序退出 */ 462 | } 463 | break; 464 | 465 | case EAP_FAILURE: 466 | alarm(0); //取消闹钟 467 | fprintf(stdout, ">>Protocol: EAP_FAILURE\n"); 468 | if(auto_rec) 469 | { 470 | fprintf(stdout, "&&Info: Authentication Failed, auto reconnect in a few sec...\n"); 471 | auto_reconnect(1); //重连,传入睡眠时间 472 | } else 473 | { 474 | fprintf(stdout, "&&Info: Authentication Failed!\n"); 475 | pcap_breakloop (handle); 476 | } 477 | break; 478 | 479 | case EAP_REQUEST_IDENTITY: 480 | alarm(0); //取消闹钟 481 | fprintf(stdout, ">>Protocol: REQUEST EAP-Identity\n"); 482 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 483 | memset(eap_response_ident_YD + 14 + 5, header->eap_id, 1); 484 | send_eap_packet(EAP_RESPONSE_IDENTITY); 485 | break; 486 | 487 | case EAP_REQUETS_MD5_CHALLENGE: 488 | alarm(0); //取消闹钟 489 | fprintf(stdout, ">>Protocol: REQUEST MD5-Challenge(PASSWORD)\n"); 490 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 491 | fill_password_md5((uint8_t*)header->eap_md5_challenge, header->eap_id); 492 | memset(eap_response_md5ch_YD + 14 + 5, header->eap_id, 1); 493 | send_eap_packet(EAP_RESPONSE_MD5_CHALLENGE); 494 | break; 495 | 496 | case EAP_REQUEST_IDENTITY_KEEP_ALIVE: 497 | alarm(0); //取消闹钟 498 | fprintf(stdout, ">>Protocol: REQUEST EAP_REQUEST_IDENTITY_KEEP_ALIVE\n"); 499 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 500 | global_id=header->eap_id; 501 | init_frames(); 502 | memset(eapol_keepalive_YD + 14 + 5, header->eap_id, 1); 503 | send_eap_packet(EAP_RESPONSE_IDENTITY_KEEP_ALIVE); 504 | break; 505 | 506 | case EAP_REQUEST_MD5_KEEP_ALIVE: 507 | break; 508 | 509 | case EAP_NOTIFICATION: 510 | printNotification(header); 511 | exit(EXIT_FAILURE); 512 | break; 513 | 514 | default: 515 | return; 516 | } 517 | } else fprintf(stdout, "Unknown ISP Type!\n"); 518 | } 519 | 520 | /* 521 | * === FUNCTION ====================================================================== 522 | * Name: send_eap_packet 523 | * Description: 根据eap类型发送相应数据包 524 | * ===================================================================================== 525 | */ 526 | void send_eap_packet(enum EAPType send_type) 527 | { 528 | uint8_t *frame_data; 529 | int frame_length = 0; 530 | int i = 0; 531 | switch(send_type) 532 | { 533 | case EAPOL_START: 534 | { 535 | switch(isp_type) 536 | { 537 | case 'D': 538 | //电信Start发包部分 539 | frame_data= eapol_start; 540 | frame_length = sizeof(eapol_start); 541 | for (i = 0; i < 2; i++) //模仿官方客户端,认证前发送2次logoff包 542 | { 543 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff Twice for CTCC 802.1x Protocol.\n"); 544 | if ( pcap_sendpacket(handle, eapol_logoff, sizeof(eapol_logoff)) != 0 ) 545 | { 546 | fprintf(stderr,"&&IMPORTANT: Error Sending the packet: %s\n", pcap_geterr(handle)); 547 | return; 548 | } 549 | } 550 | 551 | alarm(WAIT_START_TIME_OUT); //等待回应 552 | fprintf(stdout, ">>Protocol: SEND EAPOL-Start\n"); 553 | break; 554 | 555 | case 'Y': 556 | //移动Start发包部分 557 | frame_data= eapol_start_YD; 558 | frame_length = sizeof(eapol_start_YD); 559 | alarm(WAIT_START_TIME_OUT); //等待回应 560 | fprintf(stdout, ">>Protocol: SEND EAPOL-Start\n"); 561 | break; 562 | 563 | default:fprintf(stdout, "Unknown ISP Type!\n"); 564 | } 565 | } 566 | break; 567 | 568 | case EAPOL_LOGOFF: 569 | { 570 | switch(isp_type) 571 | { 572 | case 'D': 573 | //电信Logoff发包部分 574 | frame_data = eapol_logoff; 575 | frame_length = sizeof(eapol_logoff); 576 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff\n"); 577 | break; 578 | 579 | case 'Y': 580 | //移动Logoff发包部分 581 | frame_data = eapol_logoff_YD; 582 | frame_length = sizeof(eapol_logoff_YD); 583 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff\n"); 584 | break; 585 | 586 | default:fprintf(stdout, "Unknown ISP Type!\n"); 587 | } 588 | } 589 | break; 590 | 591 | case EAP_RESPONSE_IDENTITY: 592 | { 593 | switch(isp_type) 594 | { 595 | case 'D': 596 | //电信response/identity发包部分 597 | frame_data = eap_response_ident; 598 | frame_length=96; 599 | if (0 == timeout_alarm_1x) 600 | { 601 | alarm(0); 602 | } 603 | else{ 604 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 605 | } 606 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Identity\n"); 607 | break; 608 | 609 | case 'Y': 610 | //移动response/identity发包部分 611 | frame_data = eap_response_ident_YD; 612 | frame_length = 60; 613 | if (0 == timeout_alarm_1x) 614 | { 615 | alarm(0); 616 | } 617 | else{ 618 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 619 | } 620 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Identity\n"); 621 | break; 622 | 623 | default:fprintf(stdout, "Unknown ISP Type!\n"); 624 | } 625 | } 626 | break; 627 | 628 | case EAP_RESPONSE_MD5_CHALLENGE: 629 | { 630 | switch(isp_type) 631 | { 632 | case 'D': 633 | //电信response/md5_challenge发包部分 634 | frame_data = eap_response_md5ch; 635 | frame_length = 96; 636 | if (0 == timeout_alarm_1x) 637 | { 638 | alarm(0); 639 | } 640 | else{ 641 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 642 | } 643 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Md5-Challenge\n"); 644 | break; 645 | case 'Y': 646 | //移动response/md5_challenge发包部分 647 | frame_data = eap_response_md5ch_YD; 648 | frame_length = 60; 649 | if (0 == timeout_alarm_1x) 650 | { 651 | alarm(0); 652 | } 653 | else{ 654 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 655 | } 656 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Md5-Challenge\n"); 657 | break; 658 | default:fprintf(stdout, "Unknown ISP Type!\n"); 659 | } 660 | } 661 | break; 662 | 663 | case EAP_RESPONSE_IDENTITY_KEEP_ALIVE: 664 | { 665 | switch(isp_type) 666 | { 667 | case 'D': 668 | //电信response_identity_keep_alive发包部分 669 | frame_data = eapol_keepalive; 670 | frame_length = 96; 671 | if (0 == timeout_alarm_1x) 672 | { 673 | alarm(0); 674 | } 675 | else{ 676 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 677 | } 678 | fprintf(stdout, ">>Protocol: SEND EAP_RESPONSE_IDENTITY_KEEP_ALIVE\n"); 679 | break; 680 | case 'Y': 681 | //移动response_identity_keep_alive发包部分 682 | frame_data = eapol_keepalive_YD; 683 | frame_length = 60; 684 | if (0 == timeout_alarm_1x) 685 | { 686 | alarm(0); 687 | } 688 | else{ 689 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 690 | } 691 | fprintf(stdout, ">>Protocol: SEND EAP_RESPONSE_IDENTITY_KEEP_ALIVE\n"); 692 | break; 693 | default:fprintf(stdout, "Unknown ISP Type!\n"); 694 | } 695 | } 696 | break; 697 | case EAP_REQUEST_MD5_KEEP_ALIVE: //useless 698 | break; 699 | 700 | default: 701 | fprintf(stderr,"&&IMPORTANT: Wrong Send Request Type.%02x\n", send_type); 702 | return; 703 | } 704 | 705 | if (pcap_sendpacket(handle, frame_data, frame_length) != 0) 706 | { 707 | fprintf(stderr,"&&IMPORTANT: Error Sending the packet: %s\n", pcap_geterr(handle)); 708 | return; 709 | } 710 | } 711 | 712 | 713 | /* 714 | * === FUNCTION ====================================================================== 715 | * Name: get_packet 716 | * Description: pcap的回呼函数,当收到EAPOL报文时自动被调用 717 | * ===================================================================================== 718 | */ 719 | void get_packet(uint8_t *args, const struct pcap_pkthdr *header, 720 | const uint8_t *packet) 721 | { 722 | /* declare pointers to packet headers */ 723 | const struct ether_header *ethernet; /* The ethernet header [1] */ 724 | const struct eap_header *eap_header; 725 | 726 | ethernet = (struct ether_header*)(packet); 727 | eap_header = (struct eap_header *)(packet + SIZE_ETHERNET); 728 | 729 | enum EAPType p_type = get_eap_type(eap_header); 730 | action_by_eap_type(p_type, eap_header, header, packet); 731 | return; 732 | } 733 | 734 | 735 | /* 736 | * === FUNCTION ====================================================================== 737 | * Name: init_frames 738 | * Description: 初始化发送帧的数据 739 | * ===================================================================================== 740 | */ 741 | void init_frames() 742 | { 743 | if ( isp_type == 'D' ) //电信部分 744 | { 745 | int data_index; 746 | 747 | const u_char talier_eap_resp[] = {0x00, 0x44, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 748 | //talier_eap_resp后4位用来填充IP(如果这里IP填入0.0.0.0的话可破IP绑定) 749 | memcpy ( (void *)talier_eap_resp + 5, (const void *)&local_ip, 4); //往response identity里填充IP 750 | 751 | const u_char talier_eap_md5_resp[] = {0x00, 0x44, 0x61, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00}; 752 | //talier_eap_md5_resp后4位用来填充IP(如果这里IP填入0.0.0.0的话可破IP绑定) 753 | memcpy ( (void *)talier_eap_md5_resp + 5, (const void *)&local_ip, 4); //往response identity里填充IP 754 | 755 | /***** EAPOL Header *******/ 756 | u_char eapol_header[SIZE_ETHERNET]; 757 | data_index = 0; 758 | u_short eapol_t = htons (0x888e); 759 | memcpy ( eapol_header + data_index, muticast_mac, 6 ); /* dst addr. muticast */ 760 | data_index += 6; 761 | memcpy ( eapol_header + data_index, local_mac, 6 ); /* src addr. local mac */ 762 | data_index += 6; 763 | memcpy ( eapol_header + data_index, &eapol_t, 2 ); /* frame type, 0x888e*/ 764 | 765 | /**** EAPol START ****/ 766 | u_char start_data[] = { 0x01, 0x01, 0x00, 0x00 }; 767 | memset (eapol_start, 0x00, 96 ); 768 | memcpy (eapol_start, eapol_header, 14); 769 | memcpy (eapol_start + 14, start_data, 4); 770 | memset (eapol_start + 42, 0x01, 1 ); 771 | memset (eapol_start + 43, 0x01, 1 ); 772 | 773 | /****EAPol LOGOFF ****/ 774 | u_char logoff_data[4] = {0x01, 0x02, 0x00, 0x00}; 775 | memset (eapol_logoff, 0x00, 96); 776 | memcpy (eapol_logoff, eapol_header, 14); 777 | memcpy (eapol_logoff + 14, logoff_data, 4); 778 | 779 | /****EAPol Keep alive ****/ 780 | u_char keep_data[4] = { 0x01, 0x00, 0x00, 0x19 }; 781 | u_char temp_data_keepalive[5] = { 0x02, global_id, 0x00, 0x19,0x01 }; 782 | u_char temp_888e_in_keepalive[2] = { 0x88, 0x8e }; 783 | memset (eapol_keepalive, 0x00, 96); 784 | memcpy (eapol_keepalive, muticast_mac, 6); 785 | memcpy (eapol_keepalive + 6, local_mac, 6); 786 | memcpy (eapol_keepalive + 12, temp_888e_in_keepalive, 2); 787 | memcpy (eapol_keepalive + 14, keep_data, 4 ); 788 | memcpy (eapol_keepalive + 18, temp_data_keepalive, 5); 789 | memcpy (eapol_keepalive + 23, username, username_length ); 790 | memcpy (eapol_keepalive + 23 + username_length, talier_eap_resp, 9); 791 | 792 | /* EAP RESPONSE IDENTITY */ 793 | u_char keep_data_response_ident[4] = {0x01, 0x00, 0x00, 0x19}; 794 | u_char temp_data_response_ident[5] = {0x02, global_id, 0x00, 0x19,0x01}; 795 | memset (eap_response_ident, 0x00, 96); 796 | memcpy (eap_response_ident, eapol_header, 14); 797 | memcpy (eap_response_ident + 14, keep_data_response_ident, 4); 798 | memcpy (eap_response_ident + 18, temp_data_response_ident, 5); 799 | memcpy (eap_response_ident + 23, username, username_length); 800 | memcpy (eap_response_ident + 23 + username_length, talier_eap_resp, 9); 801 | 802 | /** EAP RESPONSE MD5 Challenge **/ 803 | u_char eap_resp_md5_head[10] = {0x01, 0x00, 804 | 0x00, 31 + username_length, /* eapol-length */ 805 | 0x02, 806 | global_id, /* id to be set */ 807 | 0x00, 31 + username_length, /* eap-length */ 808 | 0x04, 0x10}; 809 | memset(eap_response_md5ch, 0x00, 14 + 4 + 6 + 16 + username_length + 14); 810 | 811 | data_index = 0; 812 | memcpy (eap_response_md5ch + data_index, eapol_header, 14); 813 | data_index += 14; 814 | memcpy (eap_response_md5ch + data_index, eap_resp_md5_head, 10); 815 | data_index += 26; // 剩余16位在收到REQ/MD5报文后由fill_password_md5填充 816 | memcpy (eap_response_md5ch + data_index, username, username_length); 817 | data_index += username_length; 818 | memcpy (eap_response_md5ch + data_index, talier_eap_md5_resp, 9); 819 | } 820 | 821 | else if(isp_type == 'Y') //移动部分 822 | { 823 | 824 | int data_index; 825 | 826 | u_char eapol_header_YD[SIZE_ETHERNET]; 827 | data_index = 0; 828 | u_short eapol_t = htons (0x888e); 829 | memcpy (eapol_header_YD + data_index, muticast_mac_YD, 6); /* dst addr. muticast */ 830 | data_index += 6; 831 | memcpy (eapol_header_YD + data_index, local_mac, 6); /* src addr. local mac */ 832 | data_index += 6; 833 | memcpy (eapol_header_YD + data_index, &eapol_t, 2); /* frame type, 0x888e*/ 834 | 835 | /**** EAPol START ****/ 836 | u_char start_data_YD[] = {0x01, 0x01, 0x00, 0x00}; 837 | memset (eapol_start_YD, 0xa5, 60); 838 | memcpy (eapol_start_YD, eapol_header_YD, 14); 839 | memcpy (eapol_start_YD + 14, start_data_YD, 4); 840 | 841 | /****EAPol LOGOFF ****/ 842 | u_char logoff_data_YD[4] = {0x01, 0x02, 0x00, 0x00}; 843 | memset (eapol_logoff_YD, 0xa5, 60); 844 | memcpy (eapol_logoff_YD, eapol_header_YD, 14); 845 | memcpy (eapol_logoff_YD + 14, logoff_data_YD, 4); 846 | 847 | /****EAPol Keep alive ****/ 848 | u_char keep_data_YD[4] = {0x01, 0xfc, 0x00, 0x0c}; 849 | memset (eapol_keepalive_YD, 0xcc, 54+ username_length); 850 | memcpy (eapol_keepalive_YD, eapol_header_YD, 14); 851 | memcpy (eapol_keepalive_YD + 14, keep_data_YD, 4); 852 | memset (eapol_keepalive_YD + 18, 0, 8); 853 | memcpy (eapol_keepalive_YD + 26, &local_ip, 4); 854 | 855 | /* EAP RESPONSE IDENTITY */ 856 | u_char eap_resp_iden_head_YD[9] = {0x01, 0x00, 857 | 0x00, 26 + username_length, /* eapol_length */ 858 | 0x02, 0x2c, 859 | 0x00, 26 + username_length, /* eap_length */ 860 | 0x01}; 861 | char str1[2] = { '#', '0' }; //固定值 862 | char str2[6] = { '#', '4', '.', '1', '.', '9' }; //版本号 863 | char buf[64]; //useless 864 | 865 | memset(eap_response_ident_YD, 0xa5, 60); 866 | data_index = 0; 867 | memcpy (eap_response_ident_YD + data_index, eapol_header_YD, 14); 868 | data_index += 14; 869 | memcpy (eap_response_ident_YD + data_index, eap_resp_iden_head_YD, 9); 870 | data_index += 9; 871 | memcpy (eap_response_ident_YD + data_index, username, username_length); 872 | data_index += username_length; 873 | memcpy (eap_response_ident_YD + data_index, str1, 2); //填充 #0 874 | data_index += 2; 875 | memcpy (eap_response_ident_YD + data_index, inet_ntop(AF_INET, &local_ip, buf, 32), 876 | strlen(inet_ntop(AF_INET, &local_ip, buf, 32))); //填充IP地址 877 | data_index += strlen(inet_ntop(AF_INET, &local_ip, buf, 32)); 878 | memcpy (eap_response_ident_YD + data_index, str2, 6); //填充#4.1.9 879 | 880 | 881 | /** EAP RESPONSE MD5 Challenge **/ 882 | u_char eap_resp_md5_head_YD[10] = {0x01, 0x00, 883 | 0x00, 6 + 16 + username_length, /* eapol-length */ 884 | 0x02, 885 | 0x00, /* id to be set */ 886 | 0x00, 6 + 16 + username_length, /* eap-length */ 887 | 0x04, 0x10}; 888 | 889 | data_index = 0; 890 | memcpy (eap_response_md5ch_YD + data_index, eapol_header_YD, 14); 891 | data_index += 14; 892 | memcpy (eap_response_md5ch_YD + data_index, eap_resp_md5_head_YD, 10); 893 | data_index += 26;// 剩余16位在收到REQ/MD5报文后由fill_password_md5填充 894 | memcpy (eap_response_md5ch_YD + data_index, username, username_length); 895 | 896 | } 897 | else fprintf(stdout, "Unknown ISP Type!\n"); 898 | 899 | } 900 | 901 | 902 | /* 903 | * === FUNCTION ====================================================================== 904 | * Name: fill_password_md5 905 | * Description: 给RESPONSE_MD5_Challenge报文填充相应的MD5值。 906 | * 只会在接受到REQUEST_MD5_Challenge报文之后才进行,因为需要 907 | * 其中的Key 908 | * ===================================================================================== 909 | */ 910 | void fill_password_md5(uint8_t attach_key[], uint8_t eap_id) 911 | { 912 | if( isp_type=='D' ) 913 | { 914 | char *psw_key; 915 | char *md5; 916 | psw_key = malloc(1 + password_length + 16); 917 | psw_key[0] = eap_id; 918 | memcpy (psw_key + 1, password, password_length); 919 | memcpy (psw_key + 1 + password_length, attach_key, 16); 920 | md5 = get_md5_digest(psw_key, 1 + password_length + 16); 921 | memcpy (eap_response_md5ch + 14 + 10, md5, 16); 922 | free (psw_key); 923 | } 924 | else if(isp_type=='Y') 925 | { 926 | char *psw_key = malloc(1 + password_length + 16); 927 | char *md5; 928 | psw_key[0] = eap_id; 929 | memcpy (psw_key + 1, password, password_length); 930 | memcpy (psw_key + 1 + password_length, attach_key, 16); 931 | 932 | #if EAP_DEBUG_ON > 0 933 | printf("DEBUGER@@: MD5-Attach-KEY:\n"); 934 | print_hex ((u_char*)attach_key, 16); 935 | #endif 936 | 937 | md5 = get_md5_digest(psw_key, 1 + password_length + 16); 938 | 939 | memset (eap_response_md5ch_YD + 14 + 5, eap_id, 1); 940 | memcpy (eap_response_md5ch_YD + 14 + 10, md5, 16); 941 | 942 | free (psw_key); 943 | } 944 | } 945 | 946 | /* 947 | * === FUNCTION ====================================================================== 948 | * Name: fill_uname_md5 949 | * Description: 给RESPONSE_MD5_KEEP_ALIVE报文填充相应的MD5值。 950 | * 只会在接受到REQUEST_MD5_KEEP_ALIVE报文之后才进行,因为需要 951 | * 其中的Key 952 | * ===================================================================================== 953 | */ 954 | void fill_uname_md5(uint8_t attach_key[], uint8_t eap_id) 955 | { 956 | char *uname_key; 957 | char *md5; 958 | 959 | uname_key = malloc(username_length + 4); 960 | memcpy (uname_key, username, username_length); 961 | memcpy (uname_key + username_length, attach_key, 4); 962 | 963 | md5 = get_md5_digest(uname_key,username_length + 4); 964 | eap_response_md5ch[14+5]=eap_id; 965 | memcpy (eap_response_md5ch + 13 + 10, md5, 16); 966 | 967 | free (uname_key); 968 | } 969 | 970 | 971 | /* 972 | * === FUNCTION ====================================================================== 973 | * Name: init_info 974 | * Description: 初始化本地信息。 975 | * ===================================================================================== 976 | */ 977 | void init_info() 978 | { 979 | if(username == NULL || password == NULL){ 980 | fprintf (stderr,"Error: NO Username or Password promoted.\n" 981 | "Try sguclient --help for usage.\n"); 982 | exit(EXIT_FAILURE); 983 | } 984 | 985 | username_length = strlen(username); 986 | password_length = strlen(password); 987 | 988 | if (user_ip) 989 | local_ip = inet_addr (user_ip); 990 | else 991 | local_ip = 0; 992 | 993 | if (user_mask) 994 | local_mask = inet_addr (user_mask); 995 | else 996 | local_mask = 0; 997 | 998 | if (user_gateway) 999 | local_gateway = inet_addr (user_gateway); 1000 | else 1001 | local_gateway = 0; 1002 | 1003 | if (user_dns) 1004 | local_dns = inet_addr (user_dns); 1005 | else 1006 | local_dns = 0; 1007 | 1008 | if (local_ip == -1 || local_mask == -1 || local_gateway == -1 || local_dns == -1) { 1009 | fprintf (stderr,"ERROR: One of specified IP, MASK, Gateway and DNS address\n" 1010 | "in the arguments format error.\n"); 1011 | exit(EXIT_FAILURE); 1012 | } 1013 | } 1014 | 1015 | 1016 | /* 1017 | * === FUNCTION ====================================================================== 1018 | * Name: init_device 1019 | * Description: 初始化设备。主要是找到打开网卡、获取网卡MAC、IP, 1020 | * 同时设置pcap的初始化工作句柄。 1021 | * ===================================================================================== 1022 | */ 1023 | void init_device() 1024 | { 1025 | struct bpf_program fp; /* compiled filter program (expression) */ 1026 | char filter_exp[51]; /* filter expression [3] */ 1027 | pcap_if_t *alldevs; 1028 | pcap_addr_t *addrs; 1029 | 1030 | /* Retrieve the device list */ 1031 | if(pcap_findalldevs(&alldevs, errbuf) == -1) 1032 | { 1033 | fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); 1034 | exit(1); 1035 | } 1036 | 1037 | /* 使用第一块设备 */ 1038 | if(dev == NULL) { 1039 | dev = alldevs->name; 1040 | } 1041 | strcpy (dev_if_name, dev); 1042 | 1043 | if (dev == NULL) { 1044 | fprintf(stderr, "Couldn't find default device: %s\n", 1045 | errbuf); 1046 | exit(EXIT_FAILURE); 1047 | } 1048 | 1049 | /* open capture device */ 1050 | handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); 1051 | 1052 | if (handle == NULL) { 1053 | fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); 1054 | exit(EXIT_FAILURE); 1055 | } 1056 | 1057 | /* make sure we're capturing on an Ethernet device [2] */ 1058 | if (pcap_datalink(handle) != DLT_EN10MB) { 1059 | fprintf(stderr, "%s is not an Ethernet\n", dev); 1060 | exit(EXIT_FAILURE); 1061 | } 1062 | 1063 | /* Get IP ADDR and MASK */ 1064 | for (addrs = alldevs->addresses; addrs; addrs=addrs->next) { 1065 | if (addrs->addr->sa_family == AF_INET) { 1066 | local_ip = ((struct sockaddr_in *)addrs->addr)->sin_addr.s_addr; 1067 | local_mask = ((struct sockaddr_in *)addrs->netmask)->sin_addr.s_addr; 1068 | } 1069 | } 1070 | #ifdef __linux 1071 | /* get device basic infomation */ 1072 | struct ifreq ifr; 1073 | int sock; 1074 | if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 1075 | { 1076 | perror("socket"); 1077 | exit(EXIT_FAILURE); 1078 | } 1079 | strcpy(ifr.ifr_name, dev); 1080 | 1081 | //获得网卡Mac 1082 | if(ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) 1083 | { 1084 | perror("ioctl"); 1085 | exit(EXIT_FAILURE); 1086 | } 1087 | memcpy(local_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 1088 | #else 1089 | if (bsd_get_mac (dev, local_mac) != 0) { 1090 | fprintf(stderr, "FATIL: Fail getting BSD/MACOS Mac Address.\n"); 1091 | exit(EXIT_FAILURE); 1092 | } 1093 | #endif 1094 | 1095 | /* construct the filter string */ 1096 | sprintf(filter_exp, "ether dst %02x:%02x:%02x:%02x:%02x:%02x" 1097 | " and ether proto 0x888e", 1098 | local_mac[0], local_mac[1], 1099 | local_mac[2], local_mac[3], 1100 | local_mac[4], local_mac[5]); 1101 | 1102 | /* compile the filter expression */ 1103 | if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) { 1104 | fprintf(stderr, "Couldn't parse filter %s: %s\n", 1105 | filter_exp, pcap_geterr(handle)); 1106 | exit(EXIT_FAILURE); 1107 | } 1108 | 1109 | /* apply the compiled filter */ 1110 | if (pcap_setfilter(handle, &fp) == -1) { 1111 | fprintf(stderr, "Couldn't install filter %s: %s\n", 1112 | filter_exp, pcap_geterr(handle)); 1113 | exit(EXIT_FAILURE); 1114 | } 1115 | pcap_freecode(&fp); 1116 | pcap_freealldevs(alldevs); 1117 | } 1118 | 1119 | /* 1120 | * === FUNCTION ====================================================================== 1121 | * Name: show_local_info 1122 | * Description: 显示信息 1123 | * ===================================================================================== 1124 | */ 1125 | void show_local_info () 1126 | { 1127 | char buf[64]; 1128 | char *is_auto_buf="Disabled"; 1129 | char *isp_type_buf="Unknown"; 1130 | char *timeout_alarm_1x_buf = "Enabled"; 1131 | if (1 == auto_rec) 1132 | { 1133 | is_auto_buf="Yes"; 1134 | } 1135 | if ('D' == isp_type) 1136 | { 1137 | isp_type_buf="China Telecom"; 1138 | } 1139 | if ('Y' == isp_type) 1140 | { 1141 | isp_type_buf="China Mobile"; 1142 | } 1143 | 1144 | if (0 == timeout_alarm_1x) 1145 | { 1146 | timeout_alarm_1x_buf = "Disabled"; 1147 | } 1148 | 1149 | printf("######## SGUClient %s ####\n", SGU_VER); 1150 | printf("Device: %s\n", dev_if_name); 1151 | printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 1152 | local_mac[0],local_mac[1],local_mac[2], 1153 | local_mac[3],local_mac[4],local_mac[5]); 1154 | printf("IP: %s\n", inet_ntop(AF_INET, &local_ip, buf, 32)); 1155 | printf("MASK: %s\n", inet_ntop(AF_INET, &local_mask, buf, 32)); 1156 | printf("Gateway: %s\n", inet_ntop(AF_INET, &local_gateway, buf, 32)); 1157 | printf("DNS: %s\n", inet_ntop(AF_INET, &local_dns, buf, 32)); 1158 | printf("ISP Type: %s\n", isp_type_buf); 1159 | printf("Auto Reconnect: %s\n", is_auto_buf); 1160 | if ( isp_type == 'D' ) 1161 | { 1162 | printf("Using UDP Port: %d\n", clientPort); 1163 | } 1164 | printf("1x Timeout Alarm: %s\n", timeout_alarm_1x_buf); 1165 | printf("#####################################\n"); 1166 | } 1167 | 1168 | 1169 | /* 1170 | * === FUNCTION ====================================================================== 1171 | * Name: init_arguments 1172 | * Description: 初始化和解释命令行的字符串。getopt_long 1173 | * ===================================================================================== 1174 | */ 1175 | void init_arguments(int *argc, char ***argv) 1176 | { 1177 | /* Option struct for progrm run arguments */ 1178 | static struct option long_options[] = 1179 | { 1180 | {"help", no_argument, 0, 'h'}, 1181 | {"background", no_argument, &background, 1}, 1182 | {"auto", no_argument, &auto_rec, 1}, 1183 | {"noheartbeat", no_argument, &timeout_alarm_1x, 0}, 1184 | {"device", required_argument, 0, 2}, 1185 | {"random", no_argument, 0, 'r'}, 1186 | {"username", required_argument, 0, 'u'}, 1187 | {"password", required_argument, 0, 'p'}, 1188 | {"isp", required_argument, 0, 'i'}, 1189 | {"ip", required_argument, 0, 4}, 1190 | {"mask", required_argument, 0, 5}, 1191 | {"gateway", required_argument, 0, 'g'}, 1192 | {"showinfo", no_argument, 0, 's'}, 1193 | {"dns", required_argument, 0, 'd'}, 1194 | {0, 0, 0, 0} 1195 | }; 1196 | clientPort = 61440; //初始化时,客户端默认使用61440端口,若启用random则再产生随机端口来替换 1197 | int c; 1198 | while (1) { 1199 | /* getopt_long stores the option index here. */ 1200 | int option_index = 0; 1201 | c = getopt_long ((*argc), (*argv), "u:p:i:g:d:s:r:hbl", 1202 | long_options, &option_index); 1203 | if (c == -1) 1204 | break; 1205 | switch (c) { 1206 | case 0: 1207 | break; 1208 | case 'b': 1209 | background = 1; 1210 | break; 1211 | case 2: 1212 | dev = optarg; 1213 | break; 1214 | case 3: //was abandoned 1215 | break; 1216 | case 4: 1217 | user_ip = optarg; 1218 | break; 1219 | case 5: 1220 | user_mask = optarg; 1221 | break; 1222 | case 'u': 1223 | username = optarg; 1224 | break; 1225 | case 'p': 1226 | password = optarg; 1227 | break; 1228 | case 'g': 1229 | user_gateway = optarg; 1230 | break; 1231 | case 'd': 1232 | user_dns = optarg; 1233 | break; 1234 | case 's': 1235 | show_usage(); 1236 | exit(EXIT_SUCCESS); 1237 | break; 1238 | case 'l': 1239 | exit_flag = 1; 1240 | break; 1241 | case 'h': 1242 | show_usage(); 1243 | exit(EXIT_SUCCESS); 1244 | break; 1245 | case 'i': 1246 | isp_type = *optarg; 1247 | break; 1248 | case 'r': 1249 | clientPort = generateRandomPort(); 1250 | break; 1251 | case '?': 1252 | if (optopt == 'u' || optopt == 'p'|| optopt == 'g'|| optopt == 'd') 1253 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); 1254 | exit(EXIT_FAILURE); 1255 | break; 1256 | default: 1257 | fprintf (stderr,"Unknown option character `\\x%x'.\n", c); 1258 | exit(EXIT_FAILURE); 1259 | } 1260 | } 1261 | } 1262 | 1263 | #ifndef __linux 1264 | static int bsd_get_mac(const char ifname[], uint8_t eth_addr[]) 1265 | { 1266 | struct ifreq *ifrp; 1267 | struct ifconf ifc; 1268 | char buffer[720]; 1269 | int socketfd,error,len,space=0; 1270 | ifc.ifc_len=sizeof(buffer); 1271 | len=ifc.ifc_len; 1272 | ifc.ifc_buf=buffer; 1273 | 1274 | socketfd=socket(AF_INET,SOCK_DGRAM,0); 1275 | 1276 | if((error=ioctl(socketfd,SIOCGIFCONF,&ifc))<0) 1277 | { 1278 | perror("ioctl faild"); 1279 | exit(1); 1280 | } 1281 | if(ifc.ifc_len<=len) 1282 | { 1283 | ifrp=ifc.ifc_req; 1284 | do 1285 | { 1286 | struct sockaddr *sa=&ifrp->ifr_addr; 1287 | 1288 | if(((struct sockaddr_dl *)sa)->sdl_type==IFT_ETHER) { 1289 | if (strcmp(ifname, ifrp->ifr_name) == 0){ 1290 | memcpy (eth_addr, LLADDR((struct sockaddr_dl *)&ifrp->ifr_addr), 6); 1291 | return 0; 1292 | } 1293 | } 1294 | ifrp=(struct ifreq*)(sa->sa_len+(caddr_t)&ifrp->ifr_addr); 1295 | space+=(int)sa->sa_len+sizeof(ifrp->ifr_name); 1296 | } 1297 | while(space 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | #ifndef __linux 39 | //------bsd/apple mac 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | #include 46 | #include 47 | //#include 48 | #include "md5.h" 49 | #include "public.h" 50 | #include "dprotocol.h" 51 | 52 | /* SGUClient Version */ 53 | #define SGU_VER "release 0.20" 54 | 55 | /* default snap length (maximum bytes per packet to capture) */ 56 | #define SNAP_LEN 1518 57 | 58 | /* ethernet headers are always exactly 14 bytes [1] */ 59 | #define SIZE_ETHERNET 14 60 | 61 | /* 802.1x部分的调试开关,置1时启用调试 */ 62 | #define EAP_DEBUG_ON 0 63 | 64 | /* 宏定义 802.1x等待回应数据包的等待超时时间 */ 65 | #define WAIT_START_TIME_OUT 15 //等待数据包回应,默认等待15s 66 | #define WAIT_RESPONSE_TIME_OUT 900 //等待数据包回应,默认等待15mins 67 | 68 | struct eap_header { 69 | uint8_t eapol_v; 70 | uint8_t eapol_t; 71 | uint16_t eapol_length; 72 | uint8_t eap_t; 73 | uint8_t eap_id; 74 | uint16_t eap_length; 75 | uint8_t eap_op; 76 | uint8_t eap_v_length; 77 | uint8_t eap_md5_challenge[16]; 78 | u_char eap_info_tailer[40]; 79 | }; 80 | 81 | enum EAPType { 82 | EAPOL_START, 83 | EAPOL_LOGOFF, 84 | EAP_REQUEST_IDENTITY, 85 | EAP_RESPONSE_IDENTITY, 86 | EAP_REQUEST_IDENTITY_KEEP_ALIVE, 87 | EAP_RESPONSE_IDENTITY_KEEP_ALIVE, 88 | EAP_REQUETS_MD5_CHALLENGE, 89 | EAP_RESPONSE_MD5_CHALLENGE, 90 | EAP_SUCCESS, 91 | EAP_FAILURE, 92 | ERROR, 93 | EAP_NOTIFICATION, 94 | EAP_REQUEST_MD5_KEEP_ALIVE=250 95 | }; 96 | 97 | void YD_identity_transform(); 98 | void send_eap_packet(enum EAPType send_type); 99 | void show_usage(); 100 | char* get_md5_digest(const char* str, size_t len); 101 | void action_by_eap_type(enum EAPType pType, 102 | const struct eap_header *header, 103 | const struct pcap_pkthdr *packetinfo, 104 | const uint8_t *packet); 105 | void send_eap_packet(enum EAPType send_type); 106 | void init_frames(); 107 | void init_info(); 108 | void init_device(); 109 | void init_arguments(int *argc, char ***argv); 110 | int set_device_new_ip(); 111 | void fill_password_md5(uint8_t attach_key[], uint8_t eap_id); 112 | void fill_uname_md5(uint8_t attach_key[], uint8_t eap_id); 113 | int program_running_check(); 114 | void daemon_init(void); 115 | void show_local_info(); 116 | void print_server_info (const uint8_t *packet, uint16_t packetlength); 117 | int code_convert(char *from_charset, char *to_charset, 118 | char *inbuf, size_t inlen, char *outbuf, size_t outlen); 119 | void printNotification(const struct eap_header *eap_header); 120 | void time_out_handler(); 121 | unsigned int generateRandomPort(); 122 | void print_hex(uint8_t *array, int count); 123 | void DrcomAuthenticationEntry(); 124 | void get_packet(uint8_t *args, const struct pcap_pkthdr *header,const uint8_t *packet); 125 | 126 | 127 | -------------------------------------------------------------------------------- /sguclient-linux/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = sguclient 2 | BIN_DIR = /usr/bin/ 3 | INCLUDES = 4 | LIBS = -lpcap -lpthread 5 | 6 | C_SOURCES = $(wildcard *.c) 7 | C_OBJS = $(patsubst %.c, %.o, $(C_SOURCES)) 8 | 9 | # ------------ generate the names of the object files ------------------------ 10 | OBJECTS = $(addsuffix .o,$(BASENAMES)) 11 | 12 | # ------------ generate the names of the hidden prerequisite files ----------- 13 | PREREQUISITES = $(addprefix .,$(addsuffix .d,$(BASENAMES))) 14 | 15 | # ------------ make the executable (the default goal) ------------------------ 16 | %.o:%.c 17 | $(CC) -c $<$ $(CCFLAGS) 18 | 19 | $(TARGET): $(CPP_OBJS) $(C_OBJS) 20 | $(CXX)$(LINKFLAGS) -o $(TARGET) $^ $(LIBS) 21 | 22 | all:$(TARGET) 23 | 24 | clean: 25 | rm -f $(CPP_OBJS) $(C_OBJS) 26 | rm -f $(TARGET) 27 | 28 | install: $(TARGET) 29 | cp $(TARGET) $(BIN_DIR) 30 | 31 | uninstall: 32 | rm -f $(BIN_DIR)/$(TARGET) 33 | 34 | rebuild: clean all 35 | 36 | # ============================================================================== 37 | # vim: set tabstop=2: set shiftwidth=2: 38 | -------------------------------------------------------------------------------- /sguclient-linux/dprotocol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: dprotocol.c 5 | * 6 | * Description: 主要含drcom认证的代码(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "dprotocol.h" 20 | #include "public.h" 21 | 22 | char drcom_challenge[4]; 23 | char drcom_keepalive_info[4]; 24 | char drcom_keepalive_info2[16]; 25 | char drcom_misc1_flux[4]; 26 | char drcom_misc3_flux[4]; 27 | 28 | char revData[RECV_BUF_LEN]; 29 | 30 | 31 | static int sock; 32 | static struct sockaddr_in clientaddr; 33 | static struct sockaddr_in drcomaddr; 34 | 35 | /* 36 | * === FUNCTION ====================================================================== 37 | * Name: drcom_crc32 38 | * Description: 计算drcom协议中的crc校验值 39 | * Input: *data: 指向数据包内容的指针; data_len: 数据包的长度 40 | * Output: 返回计算出来的校验值 41 | * ===================================================================================== 42 | */ 43 | uint32_t drcom_crc32(char *data, int data_len) 44 | { 45 | uint32_t ret = 0; 46 | int i = 0; 47 | for (i = 0; i < data_len;) { 48 | ret ^= *(unsigned int *) (data + i); 49 | ret &= 0xFFFFFFFF; 50 | i += 4; 51 | } 52 | 53 | // 大端小端的坑 54 | if(checkCPULittleEndian() == 0) ret = big2little_32(ret); 55 | ret = (ret * 19680126) & 0xFFFFFFFF; 56 | if(checkCPULittleEndian() == 0) ret = big2little_32(ret); 57 | 58 | return ret; 59 | } 60 | 61 | /* 62 | * === FUNCTION ====================================================================== 63 | * Name: start_request 64 | * Description: 发起drcom协议的认证(发送长度为8的数据包) 65 | * Input: 无 66 | * Output: 成功返回0;失败返回-1 67 | * ===================================================================================== 68 | */ 69 | int start_request() 70 | { 71 | const int pkt_data_len = 8; 72 | char pkt_data[8] = 73 | { 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 }; 74 | 75 | memset(revData, 0, RECV_BUF_LEN); 76 | 77 | int revLen = 78 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 79 | #if DRCOM_DEBUG_ON > 0 80 | print_hex_drcom(revData, revLen); 81 | #endif 82 | 83 | if (revData[0] != 0x07) // Start Response 84 | return -1; 85 | 86 | memcpy(drcom_challenge, revData + 8, 4); // Challenge 87 | 88 | #if DRCOM_DEBUG_ON > 0 89 | print_hex_drcom(drcom_challenge, 4); 90 | #endif 91 | 92 | return 0; 93 | } 94 | 95 | /* 96 | * === FUNCTION ====================================================================== 97 | * Name: send_login_auth 98 | * Description: 发起drcom协议的登录(发送包含用户名、主机名等信息的长度为244的数据包) 99 | * Input: 无 100 | * Output: 成功返回0 101 | * ===================================================================================== 102 | */ 103 | int send_login_auth() 104 | { 105 | const int pkt_data_len = 244; 106 | char pkt_data[pkt_data_len]; 107 | 108 | memset(pkt_data, 0, pkt_data_len); 109 | int data_index = 0; 110 | 111 | int i = 0; 112 | 113 | // header 114 | pkt_data[data_index++] = 0x07; // Code 115 | pkt_data[data_index++] = 0x01; //id 116 | pkt_data[data_index++] = 0xf4; //len(244低位) 117 | pkt_data[data_index++] = 0x00; //len(244高位) 118 | pkt_data[data_index++] = 0x03; //step 第几步 119 | pkt_data[data_index++] = strlen(user_id); //uid len 用户ID长度 120 | 121 | // mac 122 | memcpy(pkt_data + data_index, my_mac, 6); 123 | data_index += 6; 124 | 125 | // ip 126 | memcpy(pkt_data + data_index, &my_ip.sin_addr, 4); 127 | data_index += 4; 128 | 129 | // fix(4B) 130 | pkt_data[data_index++] = 0x02; 131 | pkt_data[data_index++] = 0x22; 132 | pkt_data[data_index++] = 0x00; 133 | pkt_data[data_index++] = 0x28; //changed from 0x2a to 0x28,but I do not know why. 134 | 135 | // challenge 136 | memcpy(pkt_data + data_index, drcom_challenge, 4); 137 | data_index += 4; 138 | 139 | // crc32(后面再填) 140 | pkt_data[data_index++] = 0xc7; 141 | pkt_data[data_index++] = 0x2f; 142 | pkt_data[data_index++] = 0x31; 143 | pkt_data[data_index++] = 0x01; 144 | 145 | // 做完crc32后,在把第一个字节置位0 146 | pkt_data[data_index++] = 0x7e; 147 | pkt_data[data_index++] = 0x00; 148 | pkt_data[data_index++] = 0x00; 149 | pkt_data[data_index++] = 0x00; 150 | 151 | // 0x0020 帐号 + 计算机名 152 | int user_id_length = strlen(user_id); 153 | memcpy(pkt_data + data_index, user_id, user_id_length); 154 | data_index += user_id_length; 155 | char temp[100]; 156 | memset(temp, 0, 100); 157 | strcpy(temp, "PC-"); 158 | strcat(temp, user_id); 159 | memcpy(pkt_data + data_index, temp, 32 - user_id_length); 160 | data_index += (32 - user_id_length); 161 | 162 | //0x0040 dns 1 (114.114.114.114) 163 | data_index += 12; 164 | pkt_data[data_index++] = 0x72; 165 | pkt_data[data_index++] = 0x72; 166 | pkt_data[data_index++] = 0x72; 167 | pkt_data[data_index++] = 0x72; 168 | 169 | //0x0050 170 | data_index += 16; 171 | 172 | //0x0060 173 | pkt_data[data_index++] = 0x94; 174 | data_index += 3; 175 | pkt_data[data_index++] = 0x06; 176 | data_index += 3; 177 | pkt_data[data_index++] = 0x02; 178 | data_index += 3; 179 | pkt_data[data_index++] = 0xf0; 180 | pkt_data[data_index++] = 0x23; 181 | data_index += 2; 182 | 183 | //0x0070 184 | pkt_data[data_index++] = 0x02; 185 | data_index += 2; 186 | 187 | char drcom_ver[12] = 188 | { 0x44, 0x72, 0x43, 0x4f, 0x4d, 0x00, 0xb8, 0x01, 0x28, 0x00, 189 | 0x00, 0x00 }; 190 | memcpy(pkt_data + data_index, drcom_ver, 12); 191 | data_index += 12; 192 | 193 | //0x0080 194 | data_index += 16; 195 | 196 | //0x0090 197 | data_index += 32; 198 | 199 | //0x00b0 200 | data_index += 4; 201 | char hashcode[] = "c0a5fb14fc037f53ce0cd21ef5f136b94e25d3d4"; 202 | memcpy(pkt_data + data_index, hashcode, 40); 203 | data_index += 24; 204 | 205 | memset(revData, 0, RECV_BUF_LEN); 206 | 207 | unsigned int crc = drcom_crc32(pkt_data, pkt_data_len); 208 | #if DRCOM_DEBUG_ON > 0 209 | print_hex_drcom((char *) &crc, 4); 210 | #endif 211 | 212 | memcpy(pkt_data + 24, (char *) &crc, 4); 213 | memcpy(drcom_keepalive_info, (char *) &crc, 4); 214 | // 完成crc32校验,置位0 215 | pkt_data[28] = 0x00; 216 | 217 | #if DRCOM_DEBUG_ON > 0 218 | print_hex_drcom(pkt_data,pkt_data_len); 219 | #endif 220 | 221 | int revLen = 222 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 223 | #if DRCOM_DEBUG_ON > 0 224 | print_hex_drcom(revData, revLen); 225 | #endif 226 | 227 | unsigned char *keepalive_info = revData + 16; 228 | for (i = 0; i < 16; i++) 229 | { 230 | drcom_keepalive_info2[i] = (unsigned char) ((keepalive_info[i] << (i & 0x07)) + (keepalive_info[i] >> (8 - (i & 0x07)))); 231 | } 232 | 233 | #if DRCOM_DEBUG_ON > 0 234 | print_hex_drcom(drcom_keepalive_info2, 16); 235 | #endif 236 | 237 | return 0; 238 | } 239 | 240 | /* 241 | * === FUNCTION ====================================================================== 242 | * Name: send_alive_pkt1 243 | * Description: 发起drcom协议的1类型杂项包(发送长度为40的数据包) 244 | * Input: 无 245 | * Output: 成功返回0 246 | * ===================================================================================== 247 | */ 248 | int send_alive_pkt1() 249 | { 250 | const int pkt_data_len = 40; 251 | char pkt_data[pkt_data_len]; 252 | 253 | memset(pkt_data, 0, pkt_data_len); 254 | int data_index = 0; 255 | pkt_data[data_index++] = 0x07; // Code 256 | pkt_data[data_index++] = drcom_pkt_id; //id 257 | pkt_data[data_index++] = 0x28; //len(40低位) 258 | pkt_data[data_index++] = 0x00; //len(40高位) 259 | pkt_data[data_index++] = 0x0B; // Step 260 | pkt_data[data_index++] = 0x01; 261 | 262 | pkt_data[data_index++] = 0xdc; // Fixed Unknown 263 | pkt_data[data_index++] = 0x02; 264 | 265 | pkt_data[data_index++] = 0x00; //每次加一个数 266 | pkt_data[data_index++] = 0x00; 267 | 268 | memcpy(pkt_data + 16, drcom_misc1_flux, 4); 269 | 270 | memset(revData, 0, RECV_BUF_LEN); 271 | int revLen = 272 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 273 | #if DRCOM_DEBUG_ON > 0 274 | print_hex_drcom(revData, revLen); 275 | #endif 276 | 277 | 278 | if (revData[0] != 0x07 && revData[0] !=0x4d) // Misc 279 | return -1; 280 | 281 | if (revData[5] == 0x06 || revData[0] == 0x4d) // File 282 | { 283 | return send_alive_pkt1(); 284 | } 285 | else 286 | { 287 | drcom_pkt_id++; 288 | 289 | memcpy(&drcom_misc3_flux, revData + 16, 4); 290 | return 0; 291 | } 292 | 293 | } 294 | 295 | /* 296 | * === FUNCTION ====================================================================== 297 | * Name: send_alive_pkt2 298 | * Description: 发起drcom协议的3类型杂项包(发送长度为40的数据包) 299 | * Input: 无 300 | * Output: 成功返回0 301 | * ===================================================================================== 302 | */ 303 | int send_alive_pkt2() 304 | { 305 | const int pkt_data_len = 40; 306 | char pkt_data[pkt_data_len]; 307 | 308 | memset(pkt_data, 0, pkt_data_len); 309 | int data_index = 0; 310 | pkt_data[data_index++] = 0x07; // Code 311 | pkt_data[data_index++] = drcom_pkt_id; 312 | pkt_data[data_index++] = 0x28; //len(40低位) 313 | pkt_data[data_index++] = 0x00; //len(40高位) 314 | 315 | pkt_data[data_index++] = 0x0B; // Step 316 | pkt_data[data_index++] = 0x03; 317 | 318 | pkt_data[data_index++] = 0xdc; // Fixed Unknown 319 | pkt_data[data_index++] = 0x02; 320 | 321 | pkt_data[data_index++] = 0x00; //每次加一个数 322 | pkt_data[data_index++] = 0x00; 323 | 324 | 325 | memcpy(pkt_data + 16, drcom_misc3_flux, 4); 326 | memcpy(pkt_data + 28, &my_ip, 4); 327 | 328 | memset(revData, 0, RECV_BUF_LEN); 329 | int revLen = 330 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 331 | #if DRCOM_DEBUG_ON > 0 332 | print_hex_drcom(revData, revLen); 333 | #endif 334 | 335 | drcom_pkt_id++; 336 | 337 | memcpy(drcom_misc1_flux, revData + 16, 4); 338 | return 0; 339 | 340 | } 341 | 342 | /* 343 | * === FUNCTION ====================================================================== 344 | * Name: send_alive_begin 345 | * Description: 发起drcom协议的心跳包,即“Alive,client to server per 20s”(发送长度为38的数据包) 346 | * Input: 无 347 | * Output: 成功返回0 348 | * ===================================================================================== 349 | */ 350 | int send_alive_begin() //keepalive 351 | { 352 | const int pkt_data_len = 38; 353 | char pkt_data[pkt_data_len]; 354 | memset(pkt_data, 0, pkt_data_len); 355 | int data_index = 0; 356 | 357 | pkt_data[data_index++] = 0xff; // Code 358 | 359 | memcpy(pkt_data + data_index, drcom_keepalive_info, 4); 360 | data_index += 19; 361 | 362 | memcpy(pkt_data + data_index, drcom_keepalive_info2, 16); 363 | data_index += 16; 364 | 365 | memset(revData, 0, RECV_BUF_LEN); 366 | int revLen = 367 | udp_send_and_rev(pkt_data, pkt_data_len, revData); 368 | 369 | return 0; 370 | 371 | } 372 | 373 | /* 374 | * === FUNCTION ====================================================================== 375 | * Name: init_env_d 376 | * Description: 初始化socket 377 | * Input: 无 378 | * Output: 无 379 | * ===================================================================================== 380 | */ 381 | // init socket 382 | void init_env_d() 383 | { 384 | memset(&clientaddr, 0, sizeof(clientaddr)); 385 | clientaddr.sin_family = AF_INET; 386 | clientaddr.sin_port = htons(clientPort); 387 | clientaddr.sin_addr = my_ip.sin_addr; 388 | 389 | memset(&drcomaddr, 0, sizeof(drcomaddr)); 390 | drcomaddr.sin_family = AF_INET; 391 | drcomaddr.sin_port = htons(DR_PORT); 392 | inet_pton(AF_INET, DR_SERVER_IP, &drcomaddr.sin_addr); 393 | 394 | sock = socket(AF_INET, SOCK_DGRAM, 0); 395 | if( -1 == sock) 396 | { 397 | perror("Create drcom socket failed"); 398 | exit(-1); 399 | } 400 | 401 | if( 0 != bind(sock, (struct sockaddr *) &clientaddr, sizeof(clientaddr))) 402 | { 403 | perror("Bind drcom sock failed"); 404 | exit(-1); 405 | } 406 | } 407 | 408 | /* 409 | * === FUNCTION ====================================================================== 410 | * Name: init_dial_env 411 | * Description: 初始化拨号环境 412 | * Input: 无 413 | * Output: 无 414 | * ===================================================================================== 415 | */ 416 | void init_dial_env() 417 | { 418 | /* linklayer broadcast address, used to connect the huawei's exchange */ 419 | //const char dev_dest[ETH_ALEN] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 420 | const char dev_dest[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 421 | 422 | 423 | /* set struct sockaddr_ll for sendto function 424 | sa_ll: global value, in "xprotocol.h" */ 425 | sa_ll.sll_family = PF_PACKET; 426 | sa_ll.sll_protocol = htons(ETH_P_ALL); 427 | sa_ll.sll_ifindex = if_nametoindex(interface_name); 428 | sa_ll.sll_hatype = 0; 429 | sa_ll.sll_pkttype = PACKET_HOST | PACKET_BROADCAST | PACKET_MULTICAST; 430 | memcpy(sa_ll.sll_addr, dev_dest, ETH_ALEN); 431 | 432 | sock = create_ethhdr_sock(ð_header); // eth_header,sock: global value 433 | 434 | } 435 | 436 | /* 437 | * === FUNCTION ====================================================================== 438 | * Name: udp_send_and_rev 439 | * Description: 发送并接收udp协议的数据包 440 | * Input: *send_buf: 指向待发送数据的指针; send_len: 待发送数据的长度; 441 | *recv_buf: 指向接收缓冲区的指针 442 | * Output: 返回接收的长度 443 | * ===================================================================================== 444 | */ 445 | int udp_send_and_rev(char* send_buf, int send_len, char* recv_buf) 446 | { 447 | int nrecv_send, addrlen = sizeof(struct sockaddr_in); 448 | struct sockaddr_in clntaddr; 449 | int try_times = RETRY_TIME; 450 | 451 | while(try_times--){ 452 | nrecv_send = sendto(sock, send_buf, send_len, 0, (struct sockaddr *) &drcomaddr, addrlen); 453 | if(nrecv_send == send_len) break; 454 | } 455 | 456 | try_times = RETRY_TIME; 457 | while(try_times--){ 458 | nrecv_send = recvfrom(sock, recv_buf, RECV_BUF_LEN, 0, 459 | (struct sockaddr*) &clntaddr, &addrlen); 460 | if(nrecv_send > 0 && memcmp(&clntaddr.sin_addr, &drcomaddr.sin_addr, 4) == 0) break; 461 | } 462 | 463 | return nrecv_send; 464 | } 465 | 466 | /* 467 | * === FUNCTION ====================================================================== 468 | * Name: perrorAndSleep 469 | * Description: 打印错误信息并休眠 470 | * Input: *str: 指向待打印字符串的指针 471 | * Output: 无 472 | * ===================================================================================== 473 | */ 474 | static void perrorAndSleep(char* str){ 475 | printf("%s\n", str); 476 | strcpy(dstatusMsg, str); 477 | dstatus = DOFFLINE; 478 | sleep(20); 479 | } 480 | 481 | /* 482 | * === FUNCTION ====================================================================== 483 | * Name: printAll 484 | * Description: 打印错误信息 485 | * Input: *str: 指向待打印字符串的指针 486 | * Output: 无 487 | * ===================================================================================== 488 | */ 489 | static void printAll(char* str){ 490 | printf("drcom %s\n", str); 491 | strcpy(dstatusMsg, str); 492 | } 493 | 494 | /* 495 | * === FUNCTION ====================================================================== 496 | * Name: serve_forever_d 497 | * Description: drcom认证主程序 498 | * Input: *args: 传入的参数指针(并不需要) 499 | * Output: 无 500 | * ===================================================================================== 501 | */ 502 | void* serve_forever_d(void *args) 503 | { 504 | int ret; 505 | 506 | drcom_pkt_id = 0; 507 | dstatus = DOFFLINE; 508 | strcpy(dstatusMsg, "please log on first"); 509 | 510 | int needToSendXStart = 1; 511 | 512 | while(1) 513 | { 514 | sleep(2); 515 | if ( xstatus == XOFFLINE) //802.1x还没有上线 516 | { 517 | continue ; 518 | } 519 | 520 | if ( needToSendXStart ) 521 | { 522 | ret = start_request(); 523 | if(ret != 0) 524 | { 525 | printf("login = start request error\n"); 526 | return NULL; 527 | } 528 | needToSendXStart = 0; 529 | } 530 | 531 | if ( (revData[0] == 0x07) && (revData[2] == 0x10) ) //Misc,Response for alive(or Misc,File) 532 | { 533 | printf("Drcom Got: Misc,Response for alive(or Misc,File)\n"); 534 | if ( dstatus == DOFFLINE ) //drcom协议 还没有上线成功 535 | { 536 | ret = send_login_auth(); 537 | if(ret != 0) 538 | { 539 | printf("login = login error\n"); 540 | continue; 541 | } 542 | } 543 | if ( dstatus == DONLINE ) //drcom协议 已经上线成功 544 | { 545 | sleep(3); 546 | ret = send_alive_pkt1(); 547 | if(ret != 0) 548 | { 549 | printf("login = alive phase 1 error\n"); 550 | continue; 551 | } 552 | } 553 | } 554 | 555 | if ( (revData[0] == 0x07) && (revData[2] == 0x30) ) //Misc,3000 556 | { 557 | printf("Drcom Got: Misc,3000\n"); 558 | dstatus = DONLINE; 559 | printf("@@drcom login successfully!\n"); 560 | ret = send_alive_pkt1(); 561 | if(ret != 0) 562 | { 563 | printf("login = alive phase 1 error\n"); 564 | continue; 565 | } 566 | } 567 | 568 | if ( (revData[0] == 0x07) && (revData[5] == 0x02) ) //Misc Type2 569 | { 570 | printf("Drcom Got: Misc Type2\n"); 571 | ret = send_alive_pkt2(); 572 | if(ret != 0) 573 | { 574 | printf("keep = alive phase 2 error\n"); 575 | continue; 576 | } 577 | } 578 | 579 | if ( (revData[0] == 0x07) && (revData[5] == 0x04) ) //Misc Type4 580 | { 581 | printf("Drcom Got: Misc Type4\n"); 582 | printf("@@drcom keep successfully!\n"); 583 | sleep(8); 584 | ret = send_alive_begin(); 585 | if(ret != 0) 586 | { 587 | printf("keep = begin alive error\n"); 588 | continue; 589 | } 590 | } 591 | } 592 | 593 | close(sock); 594 | return NULL; 595 | } -------------------------------------------------------------------------------- /sguclient-linux/dprotocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: dprotocol.h 5 | * 6 | * Description: dprotocol.c的头文件,主要含drcom认证的代码(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #ifndef __DPROTOCOL_H 20 | #define __DPROTOCOL_H 21 | 22 | #include "public.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define DR_SERVER_IP "192.168.127.129" 39 | #define DR_PORT 61440 40 | #define RECV_BUF_LEN 1500 41 | #define RETRY_TIME 15 42 | 43 | 44 | int drcom_pkt_id; 45 | int dstatus; 46 | char dstatusMsg[256]; 47 | 48 | 49 | void init_dial_env(void); 50 | void init_env_d(); 51 | int udp_send_and_rev(char* send_buf, int send_len, char* recv_buf); 52 | void* serve_forever_d(void *args); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /sguclient-linux/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: main.c 5 | * 6 | * Description: sguclient的主文件,包含主函数 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "sguclient.h" 26 | #include "public.h" 27 | #include "dprotocol.h" 28 | 29 | #define LOCKFILE "/var/run/sguclient.pid" /* 锁文件 */ 30 | 31 | #define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 32 | 33 | static void signal_interrupted (int signo); 34 | 35 | extern pcap_t *handle; 36 | extern int exit_flag; 37 | 38 | int lockfile; /* 锁文件的描述字 */ 39 | 40 | /* 41 | * === FUNCTION ====================================================================== 42 | * Name: flock_reg 43 | * Description: sguclient加锁防止重复运行 44 | * Input: 无 45 | * Output: 无 46 | * ===================================================================================== 47 | */ 48 | void flock_reg() 49 | { 50 | char buf[16]; 51 | struct flock fl; 52 | fl.l_start = 0; 53 | fl.l_whence = SEEK_SET; 54 | fl.l_len = 0; 55 | fl.l_type = F_WRLCK; 56 | fl.l_pid = getpid(); 57 | 58 | //阻塞式的加锁 59 | if (fcntl (lockfile, F_SETLKW, &fl) < 0){ 60 | perror ("fcntl_reg"); 61 | exit(1); 62 | } 63 | 64 | //把pid写入锁文件 65 | assert (0 == ftruncate (lockfile, 0) ); 66 | sprintf (buf, "%ld", (long)getpid()); 67 | assert (-1 != write (lockfile, buf, strlen(buf) + 1)); 68 | } 69 | 70 | /* 71 | * === FUNCTION ====================================================================== 72 | * Name: daemon_init 73 | * Description: 准备fork至后台 74 | * Input: 无 75 | * Output: 无 76 | * ===================================================================================== 77 | */ 78 | void daemon_init(void) 79 | { 80 | pid_t pid; 81 | int fd0; 82 | 83 | if ( (pid = fork()) < 0) 84 | perror ("Fork"); 85 | else if (pid != 0) { 86 | fprintf(stdout, "&&Info: SGUClient Forked background with PID: [%d]\n\n", pid); 87 | exit(0); 88 | } 89 | setsid(); /* become session leader */ 90 | assert (0 == chdir("/tmp")); /* change working directory */ 91 | umask(0); /* clear our file mode creation mask */ 92 | flock_reg (); 93 | 94 | fd0 = open ("/dev/null", O_RDWR); 95 | dup2 (fd0, STDIN_FILENO); 96 | dup2 (fd0, STDERR_FILENO); 97 | dup2 (fd0, STDOUT_FILENO); 98 | close (fd0); 99 | } 100 | 101 | /* 102 | * === FUNCTION ====================================================================== 103 | * Name: program_running_check 104 | * Description: 检测是否已经有锁(检测程序是否已经在运行) 105 | * Input: 无 106 | * Output: 若无锁则返回0; 若有锁则返回锁着文件的进程pid 107 | * ===================================================================================== 108 | */ 109 | int program_running_check() 110 | { 111 | struct flock fl; 112 | fl.l_start = 0; 113 | fl.l_whence = SEEK_SET; 114 | fl.l_len = 0; 115 | fl.l_type = F_WRLCK; 116 | 117 | //尝试获得文件锁 118 | if (fcntl (lockfile, F_GETLK, &fl) < 0){ 119 | perror ("fcntl_get"); 120 | exit(1); 121 | } 122 | 123 | if (exit_flag) { 124 | if (fl.l_type != F_UNLCK) { 125 | if ( kill (fl.l_pid, SIGINT) == -1 ) 126 | perror("kill"); 127 | fprintf (stdout, "&&Info: Kill Signal Sent to PID %d.\n", fl.l_pid); 128 | } 129 | else 130 | fprintf (stderr, "&&Info: NO SGUClient Running.\n"); 131 | exit (EXIT_FAILURE); 132 | } 133 | 134 | //没有锁,则给文件加锁,否则返回锁着文件的进程pid 135 | if (fl.l_type == F_UNLCK) { 136 | flock_reg (); 137 | return 0; 138 | } 139 | 140 | return fl.l_pid; 141 | } 142 | 143 | /* 144 | * === FUNCTION ====================================================================== 145 | * Name: signal_interrupted 146 | * Description: 处理Ctrl+C用户取消信号,退出整个程序 147 | * Input: signo: 捕获的信号 148 | * Output: 无 149 | * ===================================================================================== 150 | */ 151 | static void signal_interrupted(int signo) 152 | { 153 | fprintf(stdout,"\n&&Info: USER Interrupted. \n"); 154 | send_eap_packet(EAPOL_LOGOFF); 155 | pcap_breakloop (handle); 156 | } 157 | 158 | /* 159 | * === FUNCTION ====================================================================== 160 | * Name: main 161 | * Description: 主函数 162 | * Input: argc: 传入参数的个数; **argv: 传入参数 163 | * Output: 成功返回1 164 | * ===================================================================================== 165 | */ 166 | int main(int argc, char **argv) 167 | { 168 | 169 | //初始化并解释程序的启动参数 170 | init_arguments (&argc, &argv); 171 | 172 | //打开锁文件 173 | lockfile = open (LOCKFILE, O_RDWR | O_CREAT , LOCKMODE); 174 | if (lockfile < 0){ 175 | perror ("Lockfile"); 176 | exit(1); 177 | } 178 | 179 | //检测程序的副本运行(文件锁) 180 | int ins_pid; 181 | if ( (ins_pid = program_running_check ()) ) { 182 | fprintf(stderr,"@@ERROR: SGUClient Already " 183 | "Running with PID %d\n", ins_pid); 184 | fprintf(stdout, "&&Info: run 'sudo kill %d' before re-running SGUClient'\n\n", ins_pid); 185 | exit(EXIT_FAILURE); 186 | } 187 | 188 | //初始化用户信息 189 | init_info(); 190 | 191 | //初始化设备,打开网卡,获得Mac、IP等信息 192 | init_device(); 193 | 194 | //初始化发送帧的缓冲区 195 | init_frames (); 196 | 197 | signal(SIGINT,signal_interrupted); 198 | signal(SIGTERM,signal_interrupted); 199 | signal(SIGALRM,time_out_handler); //注册超时闹钟,超时则自动调用time_out_handler函数 200 | show_local_info(); 201 | 202 | //Drcom认证入口 203 | DrcomAuthenticationEntry(); 204 | 205 | //发出第一个上线请求报文 206 | send_eap_packet (EAPOL_START); 207 | 208 | //进入回呼循环。以后的动作由回呼函数get_packet驱动, 209 | //直到pcap_break_loop执行,退出程序。 210 | pcap_loop (handle, -2, get_packet, NULL); /* main loop */ 211 | pcap_close (handle); 212 | return 0; 213 | } 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /sguclient-linux/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.c is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 41 | either statically or dynamically; added missing #include 42 | in library. 43 | 2002-03-11 lpd Corrected argument list for main(), and added int return 44 | type, in test program and T value program. 45 | 2002-02-21 lpd Added missing #include in test program. 46 | 2000-07-03 lpd Patched to eliminate warnings about "constant is 47 | unsigned in ANSI C, signed in traditional"; made test program 48 | self-checking. 49 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 50 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 51 | 1999-05-03 lpd Original version. 52 | */ 53 | 54 | #include "md5.h" 55 | #include 56 | 57 | #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ 58 | #ifdef ARCH_IS_BIG_ENDIAN 59 | # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) 60 | #else 61 | # define BYTE_ORDER 0 62 | #endif 63 | 64 | #define T_MASK ((md5_word_t)~0) 65 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 66 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 67 | #define T3 0x242070db 68 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 69 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 70 | #define T6 0x4787c62a 71 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 72 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 73 | #define T9 0x698098d8 74 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 75 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 76 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 77 | #define T13 0x6b901122 78 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 79 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 80 | #define T16 0x49b40821 81 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 82 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 83 | #define T19 0x265e5a51 84 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 85 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 86 | #define T22 0x02441453 87 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 88 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 89 | #define T25 0x21e1cde6 90 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 91 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 92 | #define T28 0x455a14ed 93 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 94 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 95 | #define T31 0x676f02d9 96 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 97 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 98 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 99 | #define T35 0x6d9d6122 100 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 101 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 102 | #define T38 0x4bdecfa9 103 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 104 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 105 | #define T41 0x289b7ec6 106 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 107 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 108 | #define T44 0x04881d05 109 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 110 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 111 | #define T47 0x1fa27cf8 112 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 113 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 114 | #define T50 0x432aff97 115 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 116 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 117 | #define T53 0x655b59c3 118 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 119 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 120 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 121 | #define T57 0x6fa87e4f 122 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 123 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 124 | #define T60 0x4e0811a1 125 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 126 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 127 | #define T63 0x2ad7d2bb 128 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 129 | 130 | 131 | static void 132 | md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) 133 | { 134 | md5_word_t 135 | a = pms->abcd[0], b = pms->abcd[1], 136 | c = pms->abcd[2], d = pms->abcd[3]; 137 | md5_word_t t; 138 | #if BYTE_ORDER > 0 139 | /* Define storage only for big-endian CPUs. */ 140 | md5_word_t X[16]; 141 | #else 142 | /* Define storage for little-endian or both types of CPUs. */ 143 | md5_word_t xbuf[16]; 144 | const md5_word_t *X; 145 | #endif 146 | 147 | { 148 | #if BYTE_ORDER == 0 149 | /* 150 | * Determine dynamically whether this is a big-endian or 151 | * little-endian machine, since we can use a more efficient 152 | * algorithm on the latter. 153 | */ 154 | static const int w = 1; 155 | 156 | if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ 157 | #endif 158 | #if BYTE_ORDER <= 0 /* little-endian */ 159 | { 160 | /* 161 | * On little-endian machines, we can process properly aligned 162 | * data without copying it. 163 | */ 164 | if (!((data - (const md5_byte_t *)0) & 3)) { 165 | /* data are properly aligned */ 166 | X = (const md5_word_t *)data; 167 | } else { 168 | /* not aligned */ 169 | memcpy(xbuf, data, 64); 170 | X = xbuf; 171 | } 172 | } 173 | #endif 174 | #if BYTE_ORDER == 0 175 | else /* dynamic big-endian */ 176 | #endif 177 | #if BYTE_ORDER >= 0 /* big-endian */ 178 | { 179 | /* 180 | * On big-endian machines, we must arrange the bytes in the 181 | * right order. 182 | */ 183 | const md5_byte_t *xp = data; 184 | int i; 185 | 186 | # if BYTE_ORDER == 0 187 | X = xbuf; /* (dynamic only) */ 188 | # else 189 | # define xbuf X /* (static only) */ 190 | # endif 191 | for (i = 0; i < 16; ++i, xp += 4) 192 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 193 | } 194 | #endif 195 | } 196 | 197 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 198 | 199 | /* Round 1. */ 200 | /* Let [abcd k s i] denote the operation 201 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 202 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 203 | #define SET(a, b, c, d, k, s, Ti)\ 204 | t = a + F(b,c,d) + X[k] + Ti;\ 205 | a = ROTATE_LEFT(t, s) + b 206 | /* Do the following 16 operations. */ 207 | SET(a, b, c, d, 0, 7, T1); 208 | SET(d, a, b, c, 1, 12, T2); 209 | SET(c, d, a, b, 2, 17, T3); 210 | SET(b, c, d, a, 3, 22, T4); 211 | SET(a, b, c, d, 4, 7, T5); 212 | SET(d, a, b, c, 5, 12, T6); 213 | SET(c, d, a, b, 6, 17, T7); 214 | SET(b, c, d, a, 7, 22, T8); 215 | SET(a, b, c, d, 8, 7, T9); 216 | SET(d, a, b, c, 9, 12, T10); 217 | SET(c, d, a, b, 10, 17, T11); 218 | SET(b, c, d, a, 11, 22, T12); 219 | SET(a, b, c, d, 12, 7, T13); 220 | SET(d, a, b, c, 13, 12, T14); 221 | SET(c, d, a, b, 14, 17, T15); 222 | SET(b, c, d, a, 15, 22, T16); 223 | #undef SET 224 | 225 | /* Round 2. */ 226 | /* Let [abcd k s i] denote the operation 227 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 228 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 229 | #define SET(a, b, c, d, k, s, Ti)\ 230 | t = a + G(b,c,d) + X[k] + Ti;\ 231 | a = ROTATE_LEFT(t, s) + b 232 | /* Do the following 16 operations. */ 233 | SET(a, b, c, d, 1, 5, T17); 234 | SET(d, a, b, c, 6, 9, T18); 235 | SET(c, d, a, b, 11, 14, T19); 236 | SET(b, c, d, a, 0, 20, T20); 237 | SET(a, b, c, d, 5, 5, T21); 238 | SET(d, a, b, c, 10, 9, T22); 239 | SET(c, d, a, b, 15, 14, T23); 240 | SET(b, c, d, a, 4, 20, T24); 241 | SET(a, b, c, d, 9, 5, T25); 242 | SET(d, a, b, c, 14, 9, T26); 243 | SET(c, d, a, b, 3, 14, T27); 244 | SET(b, c, d, a, 8, 20, T28); 245 | SET(a, b, c, d, 13, 5, T29); 246 | SET(d, a, b, c, 2, 9, T30); 247 | SET(c, d, a, b, 7, 14, T31); 248 | SET(b, c, d, a, 12, 20, T32); 249 | #undef SET 250 | 251 | /* Round 3. */ 252 | /* Let [abcd k s t] denote the operation 253 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 254 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 255 | #define SET(a, b, c, d, k, s, Ti)\ 256 | t = a + H(b,c,d) + X[k] + Ti;\ 257 | a = ROTATE_LEFT(t, s) + b 258 | /* Do the following 16 operations. */ 259 | SET(a, b, c, d, 5, 4, T33); 260 | SET(d, a, b, c, 8, 11, T34); 261 | SET(c, d, a, b, 11, 16, T35); 262 | SET(b, c, d, a, 14, 23, T36); 263 | SET(a, b, c, d, 1, 4, T37); 264 | SET(d, a, b, c, 4, 11, T38); 265 | SET(c, d, a, b, 7, 16, T39); 266 | SET(b, c, d, a, 10, 23, T40); 267 | SET(a, b, c, d, 13, 4, T41); 268 | SET(d, a, b, c, 0, 11, T42); 269 | SET(c, d, a, b, 3, 16, T43); 270 | SET(b, c, d, a, 6, 23, T44); 271 | SET(a, b, c, d, 9, 4, T45); 272 | SET(d, a, b, c, 12, 11, T46); 273 | SET(c, d, a, b, 15, 16, T47); 274 | SET(b, c, d, a, 2, 23, T48); 275 | #undef SET 276 | 277 | /* Round 4. */ 278 | /* Let [abcd k s t] denote the operation 279 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 280 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) 281 | #define SET(a, b, c, d, k, s, Ti)\ 282 | t = a + I(b,c,d) + X[k] + Ti;\ 283 | a = ROTATE_LEFT(t, s) + b 284 | /* Do the following 16 operations. */ 285 | SET(a, b, c, d, 0, 6, T49); 286 | SET(d, a, b, c, 7, 10, T50); 287 | SET(c, d, a, b, 14, 15, T51); 288 | SET(b, c, d, a, 5, 21, T52); 289 | SET(a, b, c, d, 12, 6, T53); 290 | SET(d, a, b, c, 3, 10, T54); 291 | SET(c, d, a, b, 10, 15, T55); 292 | SET(b, c, d, a, 1, 21, T56); 293 | SET(a, b, c, d, 8, 6, T57); 294 | SET(d, a, b, c, 15, 10, T58); 295 | SET(c, d, a, b, 6, 15, T59); 296 | SET(b, c, d, a, 13, 21, T60); 297 | SET(a, b, c, d, 4, 6, T61); 298 | SET(d, a, b, c, 11, 10, T62); 299 | SET(c, d, a, b, 2, 15, T63); 300 | SET(b, c, d, a, 9, 21, T64); 301 | #undef SET 302 | 303 | /* Then perform the following additions. (That is increment each 304 | of the four registers by the value it had before this block 305 | was started.) */ 306 | pms->abcd[0] += a; 307 | pms->abcd[1] += b; 308 | pms->abcd[2] += c; 309 | pms->abcd[3] += d; 310 | } 311 | 312 | void 313 | md5_init(md5_state_t *pms) 314 | { 315 | pms->count[0] = pms->count[1] = 0; 316 | pms->abcd[0] = 0x67452301; 317 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 318 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 319 | pms->abcd[3] = 0x10325476; 320 | } 321 | 322 | void 323 | md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) 324 | { 325 | const md5_byte_t *p = data; 326 | int left = nbytes; 327 | int offset = (pms->count[0] >> 3) & 63; 328 | md5_word_t nbits = (md5_word_t)(nbytes << 3); 329 | 330 | if (nbytes <= 0) 331 | return; 332 | 333 | /* Update the message length. */ 334 | pms->count[1] += nbytes >> 29; 335 | pms->count[0] += nbits; 336 | if (pms->count[0] < nbits) 337 | pms->count[1]++; 338 | 339 | /* Process an initial partial block. */ 340 | if (offset) { 341 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 342 | 343 | memcpy(pms->buf + offset, p, copy); 344 | if (offset + copy < 64) 345 | return; 346 | p += copy; 347 | left -= copy; 348 | md5_process(pms, pms->buf); 349 | } 350 | 351 | /* Process full blocks. */ 352 | for (; left >= 64; p += 64, left -= 64) 353 | md5_process(pms, p); 354 | 355 | /* Process a final partial block. */ 356 | if (left) 357 | memcpy(pms->buf, p, left); 358 | } 359 | 360 | void 361 | md5_finish(md5_state_t *pms, md5_byte_t digest[16]) 362 | { 363 | static const md5_byte_t pad[64] = { 364 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 365 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 366 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 367 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 368 | }; 369 | md5_byte_t data[8]; 370 | int i; 371 | 372 | /* Save the length before padding. */ 373 | for (i = 0; i < 8; ++i) 374 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 375 | /* Pad to 56 bytes mod 64. */ 376 | md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 377 | /* Append the length. */ 378 | md5_append(pms, data, 8); 379 | for (i = 0; i < 16; ++i) 380 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 381 | } 382 | -------------------------------------------------------------------------------- /sguclient-linux/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /sguclient-linux/public.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: public.c 5 | * 6 | * Description: 定义一些公有的变量和函数,主要供drcom认证使用(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "public.h" 20 | #include 21 | #include 22 | #include 23 | 24 | char EAP_TYPE_ID_SALT[9] = {0x00, 0x44, 0x61, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}; 25 | char EAP_TYPE_MD5_SALT[9] = {0x00, 0x44, 0x61, 0x2a, 0x00, 0xff, 0xff, 0xff, 0xff}; 26 | 27 | /* 28 | * === FUNCTION ====================================================================== 29 | * Name: print_mac 30 | * Description: 以一定格式打印MAC地址 31 | * Input: *src: 待打印的字符串的指针 32 | * Output: 无 33 | * ===================================================================================== 34 | */ 35 | void print_mac(char *src) 36 | { 37 | char mac[32] = ""; 38 | sprintf(mac, "%02x%02x%02x%02x%02x%02x", 39 | (unsigned char)src[0], 40 | (unsigned char)src[1], 41 | (unsigned char)src[2], 42 | (unsigned char)src[3], 43 | (unsigned char)src[4], 44 | (unsigned char)src[5]); 45 | 46 | printf("%s\n", mac); 47 | } 48 | 49 | /* 50 | * === FUNCTION ====================================================================== 51 | * Name: print_hex_drcom 52 | * Description: 打印十六进制字节流 53 | * Input: *hex: 待打印的内容的指针; len: 打印长度 54 | * Output: 无 55 | * ===================================================================================== 56 | */ 57 | #if DRCOM_DEBUG_ON > 0 58 | void print_hex_drcom(char *hex, int len) 59 | { 60 | int i; 61 | for(i=0; i>24) | 97 | (((uint32_t)(A) & 0x00ff0000) >> 8) | 98 | (((uint32_t)(A) & 0x0000ff00) << 8) | 99 | (((uint32_t)(A) & 0x000000ff) << 24)); 100 | } 101 | 102 | // create socket and get src ether address 103 | int crt_sock(struct ifreq * ifr) 104 | { 105 | int s; 106 | int err; 107 | s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); 108 | 109 | /* 110 | assert the ifr->ifr_ifrn.ifrn_name was known before 111 | interface_name was set in get_from_file(), and saved in /etc/8021.config file 112 | */ 113 | memset(ifr, 0, sizeof(struct ifreq)); 114 | strncpy(ifr->ifr_ifrn.ifrn_name, interface_name, sizeof(ifr->ifr_ifrn.ifrn_name)); // interface_name: global value, in public.h 115 | 116 | /* get ip address */ 117 | err = ioctl(s, SIOCGIFADDR, ifr); 118 | if( err < 0) 119 | { 120 | perror("ioctl get ip addr error"); 121 | close(s); 122 | return -1; 123 | } 124 | memcpy(&my_ip, &(ifr->ifr_addr), sizeof(my_ip)); 125 | 126 | /* get hardware address */ 127 | err = ioctl(s, SIOCGIFHWADDR, ifr); 128 | if( err < 0) 129 | { 130 | perror("ioctl get hw_addr error"); 131 | close(s); 132 | return -1; 133 | } 134 | 135 | // refer to: http://blog.chinaunix.net/uid-8048969-id-3417143.html 136 | err = ioctl(s, SIOCGIFFLAGS, ifr); 137 | if( err < 0) 138 | { 139 | perror("ioctl get if_flag error"); 140 | close(s); 141 | return -1; 142 | } 143 | 144 | 145 | // check the if's xstatus 146 | if(ifr->ifr_ifru.ifru_flags & IFF_RUNNING ) 147 | { 148 | printf("eth link up\n"); 149 | } 150 | else 151 | { 152 | printf("eth link down, please check the eth is ok\n"); 153 | return -1; 154 | } 155 | 156 | ifr->ifr_ifru.ifru_flags |= IFF_PROMISC; 157 | err = ioctl(s, SIOCSIFFLAGS, ifr); 158 | if( err < 0) 159 | { 160 | perror("ioctl set if_flag error"); 161 | close(s); 162 | return -1; 163 | } 164 | 165 | return s; 166 | } 167 | 168 | // the dial route all uses the same fixed eth_header and the same sock 169 | int create_ethhdr_sock(struct ethhdr * eth_header) 170 | { 171 | /* mac broadcast address, huawei's exchange */ 172 | //const char dev_dest[ETH_ALEN] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 173 | const char dev_dest[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 174 | 175 | /* acquire interface's id and hardaddress based in struct ifreq and mysock*/ 176 | struct ifreq *myifr; 177 | myifr = (struct ifreq *) malloc( sizeof(struct ifreq) ); 178 | if( NULL == myifr ) 179 | { 180 | perror("Malloc for ifreq struct failed"); 181 | exit(-1); 182 | } 183 | 184 | int mysock; 185 | mysock = crt_sock(myifr); 186 | if(-1 == mysock) 187 | { 188 | perror("Create socket failed"); 189 | exit(-1); 190 | } 191 | 192 | /* create eth header 193 | #define ETH_HLEN 14 */ 194 | memcpy(eth_header->h_dest, dev_dest, ETH_ALEN); 195 | memcpy(eth_header->h_source, myifr->ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN); 196 | memcpy(my_mac, myifr->ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN); 197 | eth_header->h_proto = htons(ETH_P_PAE); // ETH_P_PAE = 0x888e 198 | 199 | // init response salts 200 | //printf("Drcom host ip: %s\n", inet_ntoa(my_ip.sin_addr)); 201 | memcpy(EAP_TYPE_ID_SALT + sizeof(EAP_TYPE_ID_SALT) - 4, &(my_ip.sin_addr), 4); 202 | memcpy(EAP_TYPE_MD5_SALT + sizeof(EAP_TYPE_ID_SALT) - 4, &(my_ip.sin_addr), 4); 203 | 204 | free(myifr); 205 | return mysock; 206 | } 207 | -------------------------------------------------------------------------------- /sguclient-linux/public.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: public.h 5 | * 6 | * Description: public.c的头文件(修改拷贝自fsn_server) 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #ifndef __PUBLIC_H_ 20 | #define __PUBLIC_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define DOFFLINE 0 35 | #define DONLINE 1 36 | //-- 37 | #define XOFFLINE 0 38 | #define XONLINE 1 39 | 40 | #define DRCOM_DEBUG_ON 0 //Drcom认证部分的调试开关,置1时输出有关调试信息 41 | 42 | int xstatus; //802.1x状态 43 | struct sockaddr_ll sa_ll; 44 | struct ethhdr eth_header; 45 | char nodifyMsg[256]; 46 | 47 | 48 | char user_id[32]; 49 | char passwd[32]; 50 | char interface_name[32]; 51 | char listen_ip[32]; 52 | int listen_port; 53 | 54 | unsigned int clientPort; 55 | 56 | struct sockaddr_in my_ip; 57 | char my_mac[ETH_ALEN]; 58 | 59 | 60 | void print_mac(char *src); 61 | #if DRCOM_DEBUG_ON > 0 62 | void print_hex_drcom(char *hex, int len); 63 | #endif 64 | int checkCPULittleEndian(); 65 | uint32_t big2little_32(uint32_t A); 66 | int create_ethhdr_sock(struct ethhdr * eth_header); 67 | int crt_sock(struct ifreq * ifr); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /sguclient-linux/sguclient: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dafeiyoung/sguclient/1865e962ab4503b5e0be0591fc7e4807c1864716/sguclient-linux/sguclient -------------------------------------------------------------------------------- /sguclient-linux/sguclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: sguclient.c 5 | * 6 | * Description: sguclient的主文件,主要包含802.1x认证部分的代码 7 | * 8 | * Version: 0.18 9 | * Created: 10 | * Revision: none 11 | * Compiler: g++ 12 | * 13 | * Author: 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #include "sguclient.h" 20 | 21 | //#include 22 | 23 | #ifndef __linux 24 | static int bsd_get_mac(const char ifname[], uint8_t eth_addr[]); 25 | #endif 26 | 27 | /* ##### GLOBLE VAR DEFINITIONS ######################### */ 28 | /*----------------------------------------------------------------------------- 29 | * 程序的主控制变量 30 | *-----------------------------------------------------------------------------*/ 31 | char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ 32 | pcap_t *handle; /* packet capture handle */ 33 | uint8_t muticast_mac[] = /* 电信802.1x的认证服务器多播地址 */ 34 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 35 | //电信有些苑亦可用01-d0-f8-00-00-03 36 | //注意电信不可用01-80-c2-00-00-03(交换机不识别,收不到回应) 37 | 38 | uint8_t muticast_mac_YD[] = /* 移动802.1x的认证服务器多播地址 */ 39 | {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03}; 40 | //注意:移动多播地址若改为0xff广播,会增强稳定性, 41 | //但紫竹苑将完全无法使用(交换机不识别,收不到回应) 42 | 43 | 44 | /* ##### GLOBLE VAR DEFINITIONS ################### 45 | *----------------------------------------------------------------------------- 46 | * 用户信息的赋值变量,由init_argument函数初始化 47 | *-----------------------------------------------------------------------------*/ 48 | int dhcp_on = 0; /* DHCP 模式标记 */ 49 | int background = 0; /* 后台运行标记 */ 50 | char isp_type='D'; /* 运营商类型,默认是电信(西区) D电信 Y移动 */ 51 | char *dev = NULL; /* 连接的设备名 */ 52 | char *username = NULL; 53 | char *password = NULL; 54 | char *user_gateway = NULL; /* 由用户设定的四个报文参数 */ 55 | char *user_dns = NULL; 56 | char *user_ip = NULL; 57 | char *user_mask = NULL; 58 | int exit_flag = 0; 59 | int auto_rec = 0; /* 断线重拨 */ 60 | int timeout_alarm_1x = 1; 61 | int reconnect_times = 0; /* 超时重连次数 */ 62 | 63 | /* ##### GLOBLE VAR DEFINITIONS ######################### 64 | *----------------------------------------------------------------------------- 65 | * 报文相关信息变量,由init_info 、init_device函数初始化。 66 | *-----------------------------------------------------------------------------*/ 67 | char dev_if_name[64]; 68 | size_t username_length; 69 | size_t password_length; 70 | uint32_t local_ip; /* 网卡IP,网络序,下同 */ 71 | uint32_t local_mask; /* subnet mask */ 72 | uint32_t local_gateway = -1; 73 | uint32_t local_dns = -1; 74 | uint8_t local_mac[ETHER_ADDR_LEN]; /* MAC地址 */ 75 | 76 | 77 | /* ##### TYPE DEFINITIONS ######################### */ 78 | /*----------------------------------------------------------------------------- 79 | * 报文缓冲区,由init_frame函数初始化。 80 | *-----------------------------------------------------------------------------*/ 81 | u_char eapol_start[96]; /* 电信EAPOL START报文 */ 82 | u_char eapol_logoff[96]; /* 电信EAPOL LogOff报文 */ 83 | u_char eapol_keepalive[96]; 84 | u_char eap_response_ident[96]; /* 电信EAP RESPON/IDENTITY报文 */ 85 | u_char eap_response_md5ch[96]; /* 电信EAP RESPON/MD5 报文 */ 86 | 87 | u_char eapol_start_YD[60]; /* 移动EAPOL START报文 */ 88 | u_char eapol_logoff_YD[60]; /* 移动EAPOL LogOff报文 */ 89 | u_char eapol_keepalive_YD[60]; 90 | u_char eap_response_ident_YD[60]; /* 移动EAP RESPON/IDENTITY报文 */ 91 | u_char eap_response_md5ch_YD[60]; /* 移动EAP RESPON/MD5 报文 */ 92 | 93 | uint8_t global_id = 1; //EAP/EAPOL数据包的ID号,不能改为0,否则无法认证 94 | 95 | /* 96 | * === FUNCTION ====================================================================== 97 | * Name: printNotification 98 | * Description: 打印802.1x的notification信息 99 | * Input: * eap_header: 指向EAP/EAPOL数据包的结构体的指针 100 | * Output: 无 101 | * ===================================================================================== 102 | */ 103 | void printNotification(const struct eap_header *eap_header) 104 | { 105 | char *buf = (char *)eap_header; //拷贝一份EAP/EAPOL数据包供打印 106 | int i = 0; 107 | printf("\033[40;31m&&Got notification: \033[1m"); 108 | for (i = 0; i < 46; ++i) //准备打印整个EAP/EAPOL数据包 109 | { 110 | if ( (*buf >= 32) && (*buf <= 127) ) //printable 111 | { 112 | printf("%c", *buf); 113 | } 114 | buf ++; 115 | } 116 | printf("\033[40;31m\033[0m"); //end all special features 117 | printf("\n"); 118 | } 119 | 120 | /* 121 | * === FUNCTION ====================================================================== 122 | * Name: generateRandomPort 123 | * Description: 产生随机UDP端口号 124 | * Input: 无 125 | * Output: 返回产生的随机UDP端口号 126 | * ===================================================================================== 127 | */ 128 | unsigned int generateRandomPort() 129 | { 130 | unsigned int random; 131 | srand((unsigned int)time(0)); 132 | random = 10000 + rand() % 55535; 133 | return random; 134 | } 135 | 136 | /* 137 | * === FUNCTION ====================================================================== 138 | * Name: print_hex 139 | * Description: 打印十六进制字节流 140 | * Input: *array: 指向待打印内容的指针; count: 打印长度 141 | * Output: 无 142 | * ===================================================================================== 143 | */ 144 | void print_hex(uint8_t *array, int count) 145 | { 146 | int i; 147 | for(i = 0; i < count; i++){ 148 | if ( !(i % 16)) 149 | printf ("\n"); 150 | printf("%02x ", array[i]); 151 | } 152 | printf("\n"); 153 | } 154 | 155 | /* 156 | * === FUNCTION ====================================================================== 157 | * Name: DrcomAuthenticationEntry 158 | * Description: drcom认证入口 159 | * Input: 无 160 | * Output: 无 161 | * ===================================================================================== 162 | */ 163 | void DrcomAuthenticationEntry() 164 | { 165 | 166 | if (isp_type == 'D') 167 | { 168 | 169 | pthread_t dtid; //drcom线程的pid 170 | int ret; 171 | 172 | /* 173 | user_id:drcom udp协议用户名(同802.1x) 174 | passwd:drcom udp协议密码(同802.1x) 175 | interface_name:drcom udp协议认证使用的网卡设备名(同802.1x) 176 | */ 177 | strcpy(user_id,username); 178 | strcpy(passwd,password); 179 | strcpy(interface_name,dev); 180 | 181 | // init ip mac and socks 182 | init_dial_env(); 183 | init_env_d(); 184 | 185 | ret = pthread_create(&dtid, NULL, serve_forever_d, NULL); 186 | if( 0 != ret) 187 | { 188 | perror("Create Drcom Thread Failed!"); 189 | exit(EXIT_FAILURE); 190 | } 191 | else printf("Creat Drcom Thread Successfully.\n"); 192 | } 193 | else return; 194 | } 195 | 196 | /* 197 | * === FUNCTION ====================================================================== 198 | * Name: auto_reconnect 199 | * Description: 802.1x睡眠一段时间后重新发起连接的处理函数 200 | * Input: sleep_time_sec: 睡眠时间(秒) 201 | * Output: 无 202 | * ===================================================================================== 203 | */ 204 | void auto_reconnect(int sleep_time_sec) 205 | { 206 | //重新初始化一些变量 207 | global_id = 1; 208 | sleep(sleep_time_sec); 209 | send_eap_packet(EAPOL_START); 210 | } 211 | 212 | /* 213 | * === FUNCTION ====================================================================== 214 | * Name: time_out_handler 215 | * Description: 802.1x等待回应的闹钟超时处理函数 216 | * Input: 无 217 | * Output: 无 218 | * ===================================================================================== 219 | */ 220 | void time_out_handler() 221 | { 222 | printf("SGUClient wait package response time out! \nCheck your physical network connection!\n"); 223 | if ( reconnect_times >= 5 ) //重连次数超过5次 224 | { 225 | printf("SGUClient tried reconnect more than 5 times, but all failed.\n"); 226 | printf("SGUClient exits now!\n"); 227 | exit(EXIT_FAILURE); 228 | } 229 | 230 | if ( auto_rec == 1 ) 231 | { 232 | printf("Try auto reconnect in 5 secs...\n"); 233 | reconnect_times++; 234 | auto_reconnect(5); 235 | } 236 | else 237 | { 238 | printf("Auto reconnection disabled by user,SGUClient exits now!\n"); 239 | exit(EXIT_FAILURE); 240 | } 241 | } 242 | 243 | /* 244 | * === FUNCTION ====================================================================== 245 | * Name: show_usage 246 | * Description: 显示sguclient帮助信息 247 | * Input: 无 248 | * Output: 无 249 | * ===================================================================================== 250 | */ 251 | void show_usage() 252 | { 253 | printf( "\n" 254 | "SGUClient %s \n" 255 | "\t -- Supllicant for ShaoGuan University 802.1x Authentication.\n" 256 | "\t -- A client can be used on the whole campus.\n" 257 | "\t Drcom UDP protocol authentication included(Drcom 5.1.1 X,U62.R110908).\n" 258 | "\n" 259 | " Usage:\n" 260 | "\tRun under root privilege, usually by `sudo', with your \n" 261 | "\taccount info in arguments:\n\n" 262 | "\t-u, --username 802.1x username.\n" 263 | "\t-p, --password 802.1x password.\n" 264 | "\n" 265 | " Optional Arguments:\n\n" 266 | "\t--auto Enable auto reconnect. Default is disabled.\n" 267 | "\t Generally NO NEEDED!\n\n" 268 | "\t--device Specify which device to use.\n" 269 | "\t Default is usually eth0.\n\n" 270 | 271 | "\t--random Use random UDP client port during Drcom authentication.\n" 272 | "\t Sguclient will generate a random client port to replace 61440.\n" 273 | "\t Only effect the client. Server port will not be affected.\n\n" 274 | "\t--noheartbeat Disable timeout alarm clock when waiting for next 802.1x package.\n" 275 | "\t Timeout should be disabled if there is NO 802.1x heart beat package.\n\n" 276 | 277 | "\t--ip Specify your IPv4 address.\n" 278 | "\t It only takes effect when sguclient can not correctly get IP address.\n\n" 279 | 280 | "\t-b, --background Program fork to background after authentication.\n\n" 281 | 282 | "\t-i, --isp_type Specify your ISP type.\n" 283 | "\t 'D' for China Telecom(CTCC), 'Y' for China Mobile(CMCC).\n" 284 | "\t Default is D (China Telecom).\n\n" 285 | "\t-l Tell the process to Logoff.\n\n" 286 | 287 | "\t-h, --help Show this help.\n\n" 288 | "\n" 289 | " About SGUClient:\n\n" 290 | "\tThis program is a C implementation to ShaoGuan University 802.1x Authentication.\n" 291 | "\tBased on other open-source 802.1x programs,SGUClient has simple goal of replacing \n" 292 | "\tthe official clients with ONE client. \n\n" 293 | "\tWarning: This program may not be used for commercial purposes.\n\n" 294 | 295 | "\tSGUClient is a software developed individually, with NO any rela-\n" 296 | "\tiontship with ShaoGuan University or any other company.\n\n\n" 297 | 298 | "\tBug Report? Please join our QQ group: 638138948\n" 299 | "\t\t\t\t\t\t\t\t2015-09-13\n", 300 | SGU_VER); 301 | } 302 | 303 | 304 | /* 305 | * === FUNCTION ====================================================================== 306 | * Name: get_md5_digest 307 | * Description: calcuate for md5 digest 308 | * ===================================================================================== 309 | */ 310 | char* get_md5_digest(const char* str, size_t len) 311 | { 312 | static md5_byte_t digest[16]; 313 | md5_state_t state; 314 | md5_init(&state); 315 | md5_append(&state, (const md5_byte_t *)str, len); 316 | md5_finish(&state, digest); 317 | 318 | return (char*)digest; 319 | } 320 | 321 | /* 322 | * === FUNCTION ====================================================================== 323 | * Name: show_usage 324 | * Description: 根据报文的动作位返回enum EAPType内定义的报文类型 325 | * Input: *eap_header: 指向EAP\EAPOL报文结构体的指针 326 | * Output: 无 327 | * ===================================================================================== 328 | */ 329 | enum EAPType get_eap_type(const struct eap_header *eap_header) 330 | { 331 | switch (eap_header->eap_t) 332 | { 333 | case 0x01: 334 | if ( eap_header->eap_op == 0x01 ) 335 | return EAP_REQUEST_IDENTITY; 336 | if ( eap_header->eap_op == 0x04 ) 337 | return EAP_REQUETS_MD5_CHALLENGE; 338 | if ( eap_header->eap_op == 0xfa ) 339 | return EAP_REQUEST_MD5_KEEP_ALIVE; 340 | if ( eap_header->eap_op == 0x02 ) //802.1x Notification 341 | return EAP_NOTIFICATION; 342 | break; 343 | 344 | case 0x03: 345 | return EAP_SUCCESS; 346 | break; 347 | 348 | case 0x04: 349 | return EAP_FAILURE; 350 | } 351 | 352 | fprintf (stderr, "&&IMPORTANT: Unknown Package : eap_t: %02x\n" 353 | " eap_id: %02x\n" 354 | " eap_op: %02x\n", 355 | eap_header->eap_t, eap_header->eap_id, 356 | eap_header->eap_op); 357 | exit(EXIT_FAILURE); 358 | return ERROR; 359 | } 360 | 361 | 362 | /* 363 | * === FUNCTION ====================================================================== 364 | * Name: action_by_eap_type 365 | * Description: 根据eap报文的类型完成相关的应答 366 | * ===================================================================================== 367 | */ 368 | void action_by_eap_type(enum EAPType pType, 369 | const struct eap_header *header, 370 | const struct pcap_pkthdr *packetinfo, 371 | const uint8_t *packet) 372 | { 373 | if(isp_type=='D') //电信部分 374 | { 375 | printf("Received PackType: %d\n", pType); 376 | switch(pType) 377 | { 378 | case EAP_SUCCESS: 379 | alarm(0); //取消闹钟 380 | xstatus=XONLINE; 381 | fprintf(stdout, ">>Protocol: EAP_SUCCESS\n"); 382 | fprintf(stdout, "&&Info: 802.1x Authorized Access to Network. \n"); 383 | fprintf(stdout, " Then please use PPPOE manually to connect to Internet. \n"); 384 | //print_server_info (packet, packetinfo->caplen); 385 | if ( background ) 386 | { 387 | background = 0; /* 防止以后误触发 */ 388 | daemon_init(); 389 | } 390 | break; 391 | 392 | case EAP_FAILURE: 393 | alarm(0); //取消闹钟 394 | xstatus=XOFFLINE; 395 | fprintf(stdout, ">>Protocol: EAP_FAILURE\n"); 396 | if( auto_rec ) 397 | { 398 | fprintf(stdout, "&&Info: Authentication Failed, auto reconnect in a few sec...\n"); 399 | auto_reconnect(3); //重连,传入睡眠时间 400 | } 401 | else 402 | { 403 | fprintf(stdout, "&&Info: Authentication Failed!\n"); 404 | pcap_breakloop (handle); 405 | } 406 | break; 407 | 408 | case EAP_REQUEST_IDENTITY: 409 | alarm(0); //取消闹钟 410 | fprintf(stdout, ">>Protocol: REQUEST EAP-Identity\n"); 411 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 412 | global_id=header->eap_id; 413 | init_frames(); 414 | send_eap_packet(EAP_RESPONSE_IDENTITY); 415 | break; 416 | 417 | case EAP_REQUETS_MD5_CHALLENGE: 418 | alarm(0); //取消闹钟 419 | fprintf(stdout, ">>Protocol: REQUEST MD5-Challenge(PASSWORD)\n"); 420 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 421 | global_id=header->eap_id; 422 | init_frames(); 423 | fill_password_md5( (uint8_t*)header->eap_md5_challenge, header->eap_id ); 424 | send_eap_packet(EAP_RESPONSE_MD5_CHALLENGE); 425 | break; 426 | 427 | case EAP_REQUEST_IDENTITY_KEEP_ALIVE: 428 | alarm(0); //取消闹钟 429 | fprintf(stdout, ">>Protocol: REQUEST EAP_REQUEST_IDENTITY_KEEP_ALIVE\n"); 430 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 431 | global_id=header->eap_id; 432 | init_frames(); 433 | send_eap_packet(EAP_RESPONSE_IDENTITY_KEEP_ALIVE); 434 | break; 435 | 436 | case EAP_REQUEST_MD5_KEEP_ALIVE: 437 | break; 438 | 439 | case EAP_NOTIFICATION: 440 | printNotification(header); 441 | exit(EXIT_FAILURE); 442 | break; 443 | default: 444 | return; 445 | } 446 | } 447 | 448 | else if(isp_type=='Y') //移动部分 449 | { 450 | printf("Received PackType: %d\n", pType); 451 | switch(pType) 452 | { 453 | case EAP_SUCCESS: 454 | alarm(0); //取消闹钟 455 | fprintf(stdout, ">>Protocol: EAP_SUCCESS\n"); 456 | fprintf(stdout, "&&Info: 802.1x Authorized Access to Network. \n"); 457 | fprintf(stdout, " Then please use PPPOE manually to connect to Internet. \n"); 458 | if (background) 459 | { 460 | background = 0; /* 防止以后误触发 */ 461 | daemon_init (); /* fork至后台,主程序退出 */ 462 | } 463 | break; 464 | 465 | case EAP_FAILURE: 466 | alarm(0); //取消闹钟 467 | fprintf(stdout, ">>Protocol: EAP_FAILURE\n"); 468 | if(auto_rec) 469 | { 470 | fprintf(stdout, "&&Info: Authentication Failed, auto reconnect in a few sec...\n"); 471 | auto_reconnect(1); //重连,传入睡眠时间 472 | } else 473 | { 474 | fprintf(stdout, "&&Info: Authentication Failed!\n"); 475 | pcap_breakloop (handle); 476 | } 477 | break; 478 | 479 | case EAP_REQUEST_IDENTITY: 480 | alarm(0); //取消闹钟 481 | fprintf(stdout, ">>Protocol: REQUEST EAP-Identity\n"); 482 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 483 | memset(eap_response_ident_YD + 14 + 5, header->eap_id, 1); 484 | send_eap_packet(EAP_RESPONSE_IDENTITY); 485 | break; 486 | 487 | case EAP_REQUETS_MD5_CHALLENGE: 488 | alarm(0); //取消闹钟 489 | fprintf(stdout, ">>Protocol: REQUEST MD5-Challenge(PASSWORD)\n"); 490 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 491 | fill_password_md5((uint8_t*)header->eap_md5_challenge, header->eap_id); 492 | memset(eap_response_md5ch_YD + 14 + 5, header->eap_id, 1); 493 | send_eap_packet(EAP_RESPONSE_MD5_CHALLENGE); 494 | break; 495 | 496 | case EAP_REQUEST_IDENTITY_KEEP_ALIVE: 497 | alarm(0); //取消闹钟 498 | fprintf(stdout, ">>Protocol: REQUEST EAP_REQUEST_IDENTITY_KEEP_ALIVE\n"); 499 | fprintf(stdout, "DEBUGER@@ current id:%d\n",header->eap_id); 500 | global_id=header->eap_id; 501 | init_frames(); 502 | memset(eapol_keepalive_YD + 14 + 5, header->eap_id, 1); 503 | send_eap_packet(EAP_RESPONSE_IDENTITY_KEEP_ALIVE); 504 | break; 505 | 506 | case EAP_REQUEST_MD5_KEEP_ALIVE: 507 | break; 508 | 509 | case EAP_NOTIFICATION: 510 | printNotification(header); 511 | exit(EXIT_FAILURE); 512 | break; 513 | 514 | default: 515 | return; 516 | } 517 | } else fprintf(stdout, "Unknown ISP Type!\n"); 518 | } 519 | 520 | /* 521 | * === FUNCTION ====================================================================== 522 | * Name: send_eap_packet 523 | * Description: 根据eap类型发送相应数据包 524 | * ===================================================================================== 525 | */ 526 | void send_eap_packet(enum EAPType send_type) 527 | { 528 | uint8_t *frame_data; 529 | int frame_length = 0; 530 | int i = 0; 531 | switch(send_type) 532 | { 533 | case EAPOL_START: 534 | { 535 | switch(isp_type) 536 | { 537 | case 'D': 538 | //电信Start发包部分 539 | frame_data= eapol_start; 540 | frame_length = sizeof(eapol_start); 541 | for (i = 0; i < 2; i++) //模仿官方客户端,认证前发送2次logoff包 542 | { 543 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff Twice for CTCC 802.1x Protocol.\n"); 544 | if ( pcap_sendpacket(handle, eapol_logoff, sizeof(eapol_logoff)) != 0 ) 545 | { 546 | fprintf(stderr,"&&IMPORTANT: Error Sending the packet: %s\n", pcap_geterr(handle)); 547 | return; 548 | } 549 | } 550 | 551 | alarm(WAIT_START_TIME_OUT); //等待回应 552 | fprintf(stdout, ">>Protocol: SEND EAPOL-Start\n"); 553 | break; 554 | 555 | case 'Y': 556 | //移动Start发包部分 557 | frame_data= eapol_start_YD; 558 | frame_length = sizeof(eapol_start_YD); 559 | alarm(WAIT_START_TIME_OUT); //等待回应 560 | fprintf(stdout, ">>Protocol: SEND EAPOL-Start\n"); 561 | break; 562 | 563 | default:fprintf(stdout, "Unknown ISP Type!\n"); 564 | } 565 | } 566 | break; 567 | 568 | case EAPOL_LOGOFF: 569 | { 570 | switch(isp_type) 571 | { 572 | case 'D': 573 | //电信Logoff发包部分 574 | frame_data = eapol_logoff; 575 | frame_length = sizeof(eapol_logoff); 576 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff\n"); 577 | break; 578 | 579 | case 'Y': 580 | //移动Logoff发包部分 581 | frame_data = eapol_logoff_YD; 582 | frame_length = sizeof(eapol_logoff_YD); 583 | fprintf(stdout, ">>Protocol: SEND EAPOL-Logoff\n"); 584 | break; 585 | 586 | default:fprintf(stdout, "Unknown ISP Type!\n"); 587 | } 588 | } 589 | break; 590 | 591 | case EAP_RESPONSE_IDENTITY: 592 | { 593 | switch(isp_type) 594 | { 595 | case 'D': 596 | //电信response/identity发包部分 597 | frame_data = eap_response_ident; 598 | frame_length=96; 599 | if (0 == timeout_alarm_1x) 600 | { 601 | alarm(0); 602 | } 603 | else{ 604 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 605 | } 606 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Identity\n"); 607 | break; 608 | 609 | case 'Y': 610 | //移动response/identity发包部分 611 | frame_data = eap_response_ident_YD; 612 | frame_length = 60; 613 | if (0 == timeout_alarm_1x) 614 | { 615 | alarm(0); 616 | } 617 | else{ 618 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 619 | } 620 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Identity\n"); 621 | break; 622 | 623 | default:fprintf(stdout, "Unknown ISP Type!\n"); 624 | } 625 | } 626 | break; 627 | 628 | case EAP_RESPONSE_MD5_CHALLENGE: 629 | { 630 | switch(isp_type) 631 | { 632 | case 'D': 633 | //电信response/md5_challenge发包部分 634 | frame_data = eap_response_md5ch; 635 | frame_length = 96; 636 | if (0 == timeout_alarm_1x) 637 | { 638 | alarm(0); 639 | } 640 | else{ 641 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 642 | } 643 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Md5-Challenge\n"); 644 | break; 645 | case 'Y': 646 | //移动response/md5_challenge发包部分 647 | frame_data = eap_response_md5ch_YD; 648 | frame_length = 60; 649 | if (0 == timeout_alarm_1x) 650 | { 651 | alarm(0); 652 | } 653 | else{ 654 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 655 | } 656 | fprintf(stdout, ">>Protocol: SEND EAP-Response/Md5-Challenge\n"); 657 | break; 658 | default:fprintf(stdout, "Unknown ISP Type!\n"); 659 | } 660 | } 661 | break; 662 | 663 | case EAP_RESPONSE_IDENTITY_KEEP_ALIVE: 664 | { 665 | switch(isp_type) 666 | { 667 | case 'D': 668 | //电信response_identity_keep_alive发包部分 669 | frame_data = eapol_keepalive; 670 | frame_length = 96; 671 | if (0 == timeout_alarm_1x) 672 | { 673 | alarm(0); 674 | } 675 | else{ 676 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 677 | } 678 | fprintf(stdout, ">>Protocol: SEND EAP_RESPONSE_IDENTITY_KEEP_ALIVE\n"); 679 | break; 680 | case 'Y': 681 | //移动response_identity_keep_alive发包部分 682 | frame_data = eapol_keepalive_YD; 683 | frame_length = 60; 684 | if (0 == timeout_alarm_1x) 685 | { 686 | alarm(0); 687 | } 688 | else{ 689 | alarm(WAIT_RESPONSE_TIME_OUT); //等待回应 690 | } 691 | fprintf(stdout, ">>Protocol: SEND EAP_RESPONSE_IDENTITY_KEEP_ALIVE\n"); 692 | break; 693 | default:fprintf(stdout, "Unknown ISP Type!\n"); 694 | } 695 | } 696 | break; 697 | case EAP_REQUEST_MD5_KEEP_ALIVE: //useless 698 | break; 699 | 700 | default: 701 | fprintf(stderr,"&&IMPORTANT: Wrong Send Request Type.%02x\n", send_type); 702 | return; 703 | } 704 | 705 | if (pcap_sendpacket(handle, frame_data, frame_length) != 0) 706 | { 707 | fprintf(stderr,"&&IMPORTANT: Error Sending the packet: %s\n", pcap_geterr(handle)); 708 | return; 709 | } 710 | } 711 | 712 | 713 | /* 714 | * === FUNCTION ====================================================================== 715 | * Name: get_packet 716 | * Description: pcap的回呼函数,当收到EAPOL报文时自动被调用 717 | * ===================================================================================== 718 | */ 719 | void get_packet(uint8_t *args, const struct pcap_pkthdr *header, 720 | const uint8_t *packet) 721 | { 722 | /* declare pointers to packet headers */ 723 | const struct ether_header *ethernet; /* The ethernet header [1] */ 724 | const struct eap_header *eap_header; 725 | 726 | ethernet = (struct ether_header*)(packet); 727 | eap_header = (struct eap_header *)(packet + SIZE_ETHERNET); 728 | 729 | enum EAPType p_type = get_eap_type(eap_header); 730 | action_by_eap_type(p_type, eap_header, header, packet); 731 | return; 732 | } 733 | 734 | 735 | /* 736 | * === FUNCTION ====================================================================== 737 | * Name: init_frames 738 | * Description: 初始化发送帧的数据 739 | * ===================================================================================== 740 | */ 741 | void init_frames() 742 | { 743 | if ( isp_type == 'D' ) //电信部分 744 | { 745 | int data_index; 746 | 747 | const u_char talier_eap_resp[] = {0x00, 0x44, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 748 | //talier_eap_resp后4位用来填充IP(如果这里IP填入0.0.0.0的话可破IP绑定) 749 | memcpy ( (void *)talier_eap_resp + 5, (const void *)&local_ip, 4); //往response identity里填充IP 750 | 751 | const u_char talier_eap_md5_resp[] = {0x00, 0x44, 0x61, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00}; 752 | //talier_eap_md5_resp后4位用来填充IP(如果这里IP填入0.0.0.0的话可破IP绑定) 753 | memcpy ( (void *)talier_eap_md5_resp + 5, (const void *)&local_ip, 4); //往response identity里填充IP 754 | 755 | /***** EAPOL Header *******/ 756 | u_char eapol_header[SIZE_ETHERNET]; 757 | data_index = 0; 758 | u_short eapol_t = htons (0x888e); 759 | memcpy ( eapol_header + data_index, muticast_mac, 6 ); /* dst addr. muticast */ 760 | data_index += 6; 761 | memcpy ( eapol_header + data_index, local_mac, 6 ); /* src addr. local mac */ 762 | data_index += 6; 763 | memcpy ( eapol_header + data_index, &eapol_t, 2 ); /* frame type, 0x888e*/ 764 | 765 | /**** EAPol START ****/ 766 | u_char start_data[] = { 0x01, 0x01, 0x00, 0x00 }; 767 | memset (eapol_start, 0x00, 96 ); 768 | memcpy (eapol_start, eapol_header, 14); 769 | memcpy (eapol_start + 14, start_data, 4); 770 | memset (eapol_start + 42, 0x01, 1 ); 771 | memset (eapol_start + 43, 0x01, 1 ); 772 | 773 | /****EAPol LOGOFF ****/ 774 | u_char logoff_data[4] = {0x01, 0x02, 0x00, 0x00}; 775 | memset (eapol_logoff, 0x00, 96); 776 | memcpy (eapol_logoff, eapol_header, 14); 777 | memcpy (eapol_logoff + 14, logoff_data, 4); 778 | 779 | /****EAPol Keep alive ****/ 780 | u_char keep_data[4] = { 0x01, 0x00, 0x00, 0x19 }; 781 | u_char temp_data_keepalive[5] = { 0x02, global_id, 0x00, 0x19,0x01 }; 782 | u_char temp_888e_in_keepalive[2] = { 0x88, 0x8e }; 783 | memset (eapol_keepalive, 0x00, 96); 784 | memcpy (eapol_keepalive, muticast_mac, 6); 785 | memcpy (eapol_keepalive + 6, local_mac, 6); 786 | memcpy (eapol_keepalive + 12, temp_888e_in_keepalive, 2); 787 | memcpy (eapol_keepalive + 14, keep_data, 4 ); 788 | memcpy (eapol_keepalive + 18, temp_data_keepalive, 5); 789 | memcpy (eapol_keepalive + 23, username, username_length ); 790 | memcpy (eapol_keepalive + 23 + username_length, talier_eap_resp, 9); 791 | 792 | /* EAP RESPONSE IDENTITY */ 793 | u_char keep_data_response_ident[4] = {0x01, 0x00, 0x00, 0x19}; 794 | u_char temp_data_response_ident[5] = {0x02, global_id, 0x00, 0x19,0x01}; 795 | memset (eap_response_ident, 0x00, 96); 796 | memcpy (eap_response_ident, eapol_header, 14); 797 | memcpy (eap_response_ident + 14, keep_data_response_ident, 4); 798 | memcpy (eap_response_ident + 18, temp_data_response_ident, 5); 799 | memcpy (eap_response_ident + 23, username, username_length); 800 | memcpy (eap_response_ident + 23 + username_length, talier_eap_resp, 9); 801 | 802 | /** EAP RESPONSE MD5 Challenge **/ 803 | u_char eap_resp_md5_head[10] = {0x01, 0x00, 804 | 0x00, 31 + username_length, /* eapol-length */ 805 | 0x02, 806 | global_id, /* id to be set */ 807 | 0x00, 31 + username_length, /* eap-length */ 808 | 0x04, 0x10}; 809 | memset(eap_response_md5ch, 0x00, 14 + 4 + 6 + 16 + username_length + 14); 810 | 811 | data_index = 0; 812 | memcpy (eap_response_md5ch + data_index, eapol_header, 14); 813 | data_index += 14; 814 | memcpy (eap_response_md5ch + data_index, eap_resp_md5_head, 10); 815 | data_index += 26; // 剩余16位在收到REQ/MD5报文后由fill_password_md5填充 816 | memcpy (eap_response_md5ch + data_index, username, username_length); 817 | data_index += username_length; 818 | memcpy (eap_response_md5ch + data_index, talier_eap_md5_resp, 9); 819 | } 820 | 821 | else if(isp_type == 'Y') //移动部分 822 | { 823 | 824 | int data_index; 825 | 826 | u_char eapol_header_YD[SIZE_ETHERNET]; 827 | data_index = 0; 828 | u_short eapol_t = htons (0x888e); 829 | memcpy (eapol_header_YD + data_index, muticast_mac_YD, 6); /* dst addr. muticast */ 830 | data_index += 6; 831 | memcpy (eapol_header_YD + data_index, local_mac, 6); /* src addr. local mac */ 832 | data_index += 6; 833 | memcpy (eapol_header_YD + data_index, &eapol_t, 2); /* frame type, 0x888e*/ 834 | 835 | /**** EAPol START ****/ 836 | u_char start_data_YD[] = {0x01, 0x01, 0x00, 0x00}; 837 | memset (eapol_start_YD, 0xa5, 60); 838 | memcpy (eapol_start_YD, eapol_header_YD, 14); 839 | memcpy (eapol_start_YD + 14, start_data_YD, 4); 840 | 841 | /****EAPol LOGOFF ****/ 842 | u_char logoff_data_YD[4] = {0x01, 0x02, 0x00, 0x00}; 843 | memset (eapol_logoff_YD, 0xa5, 60); 844 | memcpy (eapol_logoff_YD, eapol_header_YD, 14); 845 | memcpy (eapol_logoff_YD + 14, logoff_data_YD, 4); 846 | 847 | /****EAPol Keep alive ****/ 848 | u_char keep_data_YD[4] = {0x01, 0xfc, 0x00, 0x0c}; 849 | memset (eapol_keepalive_YD, 0xcc, 54+ username_length); 850 | memcpy (eapol_keepalive_YD, eapol_header_YD, 14); 851 | memcpy (eapol_keepalive_YD + 14, keep_data_YD, 4); 852 | memset (eapol_keepalive_YD + 18, 0, 8); 853 | memcpy (eapol_keepalive_YD + 26, &local_ip, 4); 854 | 855 | /* EAP RESPONSE IDENTITY */ 856 | u_char eap_resp_iden_head_YD[9] = {0x01, 0x00, 857 | 0x00, 26 + username_length, /* eapol_length */ 858 | 0x02, 0x2c, 859 | 0x00, 26 + username_length, /* eap_length */ 860 | 0x01}; 861 | char str1[2] = { '#', '0' }; //固定值 862 | char str2[6] = { '#', '4', '.', '1', '.', '9' }; //版本号 863 | char buf[64]; //useless 864 | 865 | memset(eap_response_ident_YD, 0xa5, 60); 866 | data_index = 0; 867 | memcpy (eap_response_ident_YD + data_index, eapol_header_YD, 14); 868 | data_index += 14; 869 | memcpy (eap_response_ident_YD + data_index, eap_resp_iden_head_YD, 9); 870 | data_index += 9; 871 | memcpy (eap_response_ident_YD + data_index, username, username_length); 872 | data_index += username_length; 873 | memcpy (eap_response_ident_YD + data_index, str1, 2); //填充 #0 874 | data_index += 2; 875 | memcpy (eap_response_ident_YD + data_index, inet_ntop(AF_INET, &local_ip, buf, 32), 876 | strlen(inet_ntop(AF_INET, &local_ip, buf, 32))); //填充IP地址 877 | data_index += strlen(inet_ntop(AF_INET, &local_ip, buf, 32)); 878 | memcpy (eap_response_ident_YD + data_index, str2, 6); //填充#4.1.9 879 | 880 | 881 | /** EAP RESPONSE MD5 Challenge **/ 882 | u_char eap_resp_md5_head_YD[10] = {0x01, 0x00, 883 | 0x00, 6 + 16 + username_length, /* eapol-length */ 884 | 0x02, 885 | 0x00, /* id to be set */ 886 | 0x00, 6 + 16 + username_length, /* eap-length */ 887 | 0x04, 0x10}; 888 | 889 | data_index = 0; 890 | memcpy (eap_response_md5ch_YD + data_index, eapol_header_YD, 14); 891 | data_index += 14; 892 | memcpy (eap_response_md5ch_YD + data_index, eap_resp_md5_head_YD, 10); 893 | data_index += 26;// 剩余16位在收到REQ/MD5报文后由fill_password_md5填充 894 | memcpy (eap_response_md5ch_YD + data_index, username, username_length); 895 | 896 | } 897 | else fprintf(stdout, "Unknown ISP Type!\n"); 898 | 899 | } 900 | 901 | 902 | /* 903 | * === FUNCTION ====================================================================== 904 | * Name: fill_password_md5 905 | * Description: 给RESPONSE_MD5_Challenge报文填充相应的MD5值。 906 | * 只会在接受到REQUEST_MD5_Challenge报文之后才进行,因为需要 907 | * 其中的Key 908 | * ===================================================================================== 909 | */ 910 | void fill_password_md5(uint8_t attach_key[], uint8_t eap_id) 911 | { 912 | if( isp_type=='D' ) 913 | { 914 | char *psw_key; 915 | char *md5; 916 | psw_key = malloc(1 + password_length + 16); 917 | psw_key[0] = eap_id; 918 | memcpy (psw_key + 1, password, password_length); 919 | memcpy (psw_key + 1 + password_length, attach_key, 16); 920 | md5 = get_md5_digest(psw_key, 1 + password_length + 16); 921 | memcpy (eap_response_md5ch + 14 + 10, md5, 16); 922 | free (psw_key); 923 | } 924 | else if(isp_type=='Y') 925 | { 926 | char *psw_key = malloc(1 + password_length + 16); 927 | char *md5; 928 | psw_key[0] = eap_id; 929 | memcpy (psw_key + 1, password, password_length); 930 | memcpy (psw_key + 1 + password_length, attach_key, 16); 931 | 932 | #if EAP_DEBUG_ON > 0 933 | printf("DEBUGER@@: MD5-Attach-KEY:\n"); 934 | print_hex ((u_char*)attach_key, 16); 935 | #endif 936 | 937 | md5 = get_md5_digest(psw_key, 1 + password_length + 16); 938 | 939 | memset (eap_response_md5ch_YD + 14 + 5, eap_id, 1); 940 | memcpy (eap_response_md5ch_YD + 14 + 10, md5, 16); 941 | 942 | free (psw_key); 943 | } 944 | } 945 | 946 | /* 947 | * === FUNCTION ====================================================================== 948 | * Name: fill_uname_md5 949 | * Description: 给RESPONSE_MD5_KEEP_ALIVE报文填充相应的MD5值。 950 | * 只会在接受到REQUEST_MD5_KEEP_ALIVE报文之后才进行,因为需要 951 | * 其中的Key 952 | * ===================================================================================== 953 | */ 954 | void fill_uname_md5(uint8_t attach_key[], uint8_t eap_id) 955 | { 956 | char *uname_key; 957 | char *md5; 958 | 959 | uname_key = malloc(username_length + 4); 960 | memcpy (uname_key, username, username_length); 961 | memcpy (uname_key + username_length, attach_key, 4); 962 | 963 | md5 = get_md5_digest(uname_key,username_length + 4); 964 | eap_response_md5ch[14+5]=eap_id; 965 | memcpy (eap_response_md5ch + 13 + 10, md5, 16); 966 | 967 | free (uname_key); 968 | } 969 | 970 | 971 | /* 972 | * === FUNCTION ====================================================================== 973 | * Name: init_info 974 | * Description: 初始化本地信息。 975 | * ===================================================================================== 976 | */ 977 | void init_info() 978 | { 979 | if(username == NULL || password == NULL){ 980 | fprintf (stderr,"Error: NO Username or Password promoted.\n" 981 | "Try sguclient --help for usage.\n"); 982 | exit(EXIT_FAILURE); 983 | } 984 | 985 | username_length = strlen(username); 986 | password_length = strlen(password); 987 | 988 | if (user_ip) 989 | local_ip = inet_addr (user_ip); 990 | else 991 | local_ip = 0; 992 | 993 | if (user_mask) 994 | local_mask = inet_addr (user_mask); 995 | else 996 | local_mask = 0; 997 | 998 | if (user_gateway) 999 | local_gateway = inet_addr (user_gateway); 1000 | else 1001 | local_gateway = 0; 1002 | 1003 | if (user_dns) 1004 | local_dns = inet_addr (user_dns); 1005 | else 1006 | local_dns = 0; 1007 | 1008 | if (local_ip == -1 || local_mask == -1 || local_gateway == -1 || local_dns == -1) { 1009 | fprintf (stderr,"ERROR: One of specified IP, MASK, Gateway and DNS address\n" 1010 | "in the arguments format error.\n"); 1011 | exit(EXIT_FAILURE); 1012 | } 1013 | } 1014 | 1015 | 1016 | /* 1017 | * === FUNCTION ====================================================================== 1018 | * Name: init_device 1019 | * Description: 初始化设备。主要是找到打开网卡、获取网卡MAC、IP, 1020 | * 同时设置pcap的初始化工作句柄。 1021 | * ===================================================================================== 1022 | */ 1023 | void init_device() 1024 | { 1025 | struct bpf_program fp; /* compiled filter program (expression) */ 1026 | char filter_exp[51]; /* filter expression [3] */ 1027 | pcap_if_t *alldevs; 1028 | pcap_addr_t *addrs; 1029 | 1030 | /* Retrieve the device list */ 1031 | if(pcap_findalldevs(&alldevs, errbuf) == -1) 1032 | { 1033 | fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); 1034 | exit(1); 1035 | } 1036 | 1037 | /* 使用第一块设备 */ 1038 | if(dev == NULL) { 1039 | dev = alldevs->name; 1040 | } 1041 | strcpy (dev_if_name, dev); 1042 | 1043 | if (dev == NULL) { 1044 | fprintf(stderr, "Couldn't find default device: %s\n", 1045 | errbuf); 1046 | exit(EXIT_FAILURE); 1047 | } 1048 | 1049 | /* open capture device */ 1050 | handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); 1051 | 1052 | if (handle == NULL) { 1053 | fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); 1054 | exit(EXIT_FAILURE); 1055 | } 1056 | 1057 | /* make sure we're capturing on an Ethernet device [2] */ 1058 | if (pcap_datalink(handle) != DLT_EN10MB) { 1059 | fprintf(stderr, "%s is not an Ethernet\n", dev); 1060 | exit(EXIT_FAILURE); 1061 | } 1062 | 1063 | /* Get IP ADDR and MASK */ 1064 | for (addrs = alldevs->addresses; addrs; addrs=addrs->next) { 1065 | if (addrs->addr->sa_family == AF_INET) { 1066 | local_ip = ((struct sockaddr_in *)addrs->addr)->sin_addr.s_addr; 1067 | local_mask = ((struct sockaddr_in *)addrs->netmask)->sin_addr.s_addr; 1068 | } 1069 | } 1070 | #ifdef __linux 1071 | /* get device basic infomation */ 1072 | struct ifreq ifr; 1073 | int sock; 1074 | if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 1075 | { 1076 | perror("socket"); 1077 | exit(EXIT_FAILURE); 1078 | } 1079 | strcpy(ifr.ifr_name, dev); 1080 | 1081 | //获得网卡Mac 1082 | if(ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) 1083 | { 1084 | perror("ioctl"); 1085 | exit(EXIT_FAILURE); 1086 | } 1087 | memcpy(local_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 1088 | #else 1089 | if (bsd_get_mac (dev, local_mac) != 0) { 1090 | fprintf(stderr, "FATIL: Fail getting BSD/MACOS Mac Address.\n"); 1091 | exit(EXIT_FAILURE); 1092 | } 1093 | #endif 1094 | 1095 | /* construct the filter string */ 1096 | sprintf(filter_exp, "ether dst %02x:%02x:%02x:%02x:%02x:%02x" 1097 | " and ether proto 0x888e", 1098 | local_mac[0], local_mac[1], 1099 | local_mac[2], local_mac[3], 1100 | local_mac[4], local_mac[5]); 1101 | 1102 | /* compile the filter expression */ 1103 | if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) { 1104 | fprintf(stderr, "Couldn't parse filter %s: %s\n", 1105 | filter_exp, pcap_geterr(handle)); 1106 | exit(EXIT_FAILURE); 1107 | } 1108 | 1109 | /* apply the compiled filter */ 1110 | if (pcap_setfilter(handle, &fp) == -1) { 1111 | fprintf(stderr, "Couldn't install filter %s: %s\n", 1112 | filter_exp, pcap_geterr(handle)); 1113 | exit(EXIT_FAILURE); 1114 | } 1115 | pcap_freecode(&fp); 1116 | pcap_freealldevs(alldevs); 1117 | } 1118 | 1119 | /* 1120 | * === FUNCTION ====================================================================== 1121 | * Name: show_local_info 1122 | * Description: 显示信息 1123 | * ===================================================================================== 1124 | */ 1125 | void show_local_info () 1126 | { 1127 | char buf[64]; 1128 | char *is_auto_buf="Disabled"; 1129 | char *isp_type_buf="Unknown"; 1130 | char *timeout_alarm_1x_buf = "Enabled"; 1131 | if (1 == auto_rec) 1132 | { 1133 | is_auto_buf="Yes"; 1134 | } 1135 | if ('D' == isp_type) 1136 | { 1137 | isp_type_buf="China Telecom"; 1138 | } 1139 | if ('Y' == isp_type) 1140 | { 1141 | isp_type_buf="China Mobile"; 1142 | } 1143 | 1144 | if (0 == timeout_alarm_1x) 1145 | { 1146 | timeout_alarm_1x_buf = "Disabled"; 1147 | } 1148 | 1149 | printf("######## SGUClient %s ####\n", SGU_VER); 1150 | printf("Device: %s\n", dev_if_name); 1151 | printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 1152 | local_mac[0],local_mac[1],local_mac[2], 1153 | local_mac[3],local_mac[4],local_mac[5]); 1154 | printf("IP: %s\n", inet_ntop(AF_INET, &local_ip, buf, 32)); 1155 | printf("MASK: %s\n", inet_ntop(AF_INET, &local_mask, buf, 32)); 1156 | printf("Gateway: %s\n", inet_ntop(AF_INET, &local_gateway, buf, 32)); 1157 | printf("DNS: %s\n", inet_ntop(AF_INET, &local_dns, buf, 32)); 1158 | printf("ISP Type: %s\n", isp_type_buf); 1159 | printf("Auto Reconnect: %s\n", is_auto_buf); 1160 | if ( isp_type == 'D' ) 1161 | { 1162 | printf("Using UDP Port: %d\n", clientPort); 1163 | } 1164 | printf("1x Timeout Alarm: %s\n", timeout_alarm_1x_buf); 1165 | printf("#####################################\n"); 1166 | } 1167 | 1168 | 1169 | /* 1170 | * === FUNCTION ====================================================================== 1171 | * Name: init_arguments 1172 | * Description: 初始化和解释命令行的字符串。getopt_long 1173 | * ===================================================================================== 1174 | */ 1175 | void init_arguments(int *argc, char ***argv) 1176 | { 1177 | /* Option struct for progrm run arguments */ 1178 | static struct option long_options[] = 1179 | { 1180 | {"help", no_argument, 0, 'h'}, 1181 | {"background", no_argument, &background, 1}, 1182 | {"auto", no_argument, &auto_rec, 1}, 1183 | {"noheartbeat", no_argument, &timeout_alarm_1x, 0}, 1184 | {"device", required_argument, 0, 2}, 1185 | {"random", no_argument, 0, 'r'}, 1186 | {"username", required_argument, 0, 'u'}, 1187 | {"password", required_argument, 0, 'p'}, 1188 | {"isp", required_argument, 0, 'i'}, 1189 | {"ip", required_argument, 0, 4}, 1190 | {"mask", required_argument, 0, 5}, 1191 | {"gateway", required_argument, 0, 'g'}, 1192 | {"showinfo", no_argument, 0, 's'}, 1193 | {"dns", required_argument, 0, 'd'}, 1194 | {0, 0, 0, 0} 1195 | }; 1196 | clientPort = 61440; //初始化时,客户端默认使用61440端口,若启用random则再产生随机端口来替换 1197 | int c; 1198 | while (1) { 1199 | /* getopt_long stores the option index here. */ 1200 | int option_index = 0; 1201 | c = getopt_long ((*argc), (*argv), "u:p:i:g:d:s:r:hbl", 1202 | long_options, &option_index); 1203 | if (c == -1) 1204 | break; 1205 | switch (c) { 1206 | case 0: 1207 | break; 1208 | case 'b': 1209 | background = 1; 1210 | break; 1211 | case 2: 1212 | dev = optarg; 1213 | break; 1214 | case 3: //was abandoned 1215 | break; 1216 | case 4: 1217 | user_ip = optarg; 1218 | break; 1219 | case 5: 1220 | user_mask = optarg; 1221 | break; 1222 | case 'u': 1223 | username = optarg; 1224 | break; 1225 | case 'p': 1226 | password = optarg; 1227 | break; 1228 | case 'g': 1229 | user_gateway = optarg; 1230 | break; 1231 | case 'd': 1232 | user_dns = optarg; 1233 | break; 1234 | case 's': 1235 | show_usage(); 1236 | exit(EXIT_SUCCESS); 1237 | break; 1238 | case 'l': 1239 | exit_flag = 1; 1240 | break; 1241 | case 'h': 1242 | show_usage(); 1243 | exit(EXIT_SUCCESS); 1244 | break; 1245 | case 'i': 1246 | isp_type = *optarg; 1247 | break; 1248 | case 'r': 1249 | clientPort = generateRandomPort(); 1250 | break; 1251 | case '?': 1252 | if (optopt == 'u' || optopt == 'p'|| optopt == 'g'|| optopt == 'd') 1253 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); 1254 | exit(EXIT_FAILURE); 1255 | break; 1256 | default: 1257 | fprintf (stderr,"Unknown option character `\\x%x'.\n", c); 1258 | exit(EXIT_FAILURE); 1259 | } 1260 | } 1261 | } 1262 | 1263 | #ifndef __linux 1264 | static int bsd_get_mac(const char ifname[], uint8_t eth_addr[]) 1265 | { 1266 | struct ifreq *ifrp; 1267 | struct ifconf ifc; 1268 | char buffer[720]; 1269 | int socketfd,error,len,space=0; 1270 | ifc.ifc_len=sizeof(buffer); 1271 | len=ifc.ifc_len; 1272 | ifc.ifc_buf=buffer; 1273 | 1274 | socketfd=socket(AF_INET,SOCK_DGRAM,0); 1275 | 1276 | if((error=ioctl(socketfd,SIOCGIFCONF,&ifc))<0) 1277 | { 1278 | perror("ioctl faild"); 1279 | exit(1); 1280 | } 1281 | if(ifc.ifc_len<=len) 1282 | { 1283 | ifrp=ifc.ifc_req; 1284 | do 1285 | { 1286 | struct sockaddr *sa=&ifrp->ifr_addr; 1287 | 1288 | if(((struct sockaddr_dl *)sa)->sdl_type==IFT_ETHER) { 1289 | if (strcmp(ifname, ifrp->ifr_name) == 0){ 1290 | memcpy (eth_addr, LLADDR((struct sockaddr_dl *)&ifrp->ifr_addr), 6); 1291 | return 0; 1292 | } 1293 | } 1294 | ifrp=(struct ifreq*)(sa->sa_len+(caddr_t)&ifrp->ifr_addr); 1295 | space+=(int)sa->sa_len+sizeof(ifrp->ifr_name); 1296 | } 1297 | while(space 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | #ifndef __linux 39 | //------bsd/apple mac 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | #include 46 | #include 47 | //#include 48 | #include "md5.h" 49 | #include "public.h" 50 | #include "dprotocol.h" 51 | 52 | /* SGUClient Version */ 53 | #define SGU_VER "release 0.20" 54 | 55 | /* default snap length (maximum bytes per packet to capture) */ 56 | #define SNAP_LEN 1518 57 | 58 | /* ethernet headers are always exactly 14 bytes [1] */ 59 | #define SIZE_ETHERNET 14 60 | 61 | /* 802.1x部分的调试开关,置1时启用调试 */ 62 | #define EAP_DEBUG_ON 0 63 | 64 | /* 宏定义 802.1x等待回应数据包的等待超时时间 */ 65 | #define WAIT_START_TIME_OUT 15 //等待数据包回应,默认等待15s 66 | #define WAIT_RESPONSE_TIME_OUT 900 //等待数据包回应,默认等待15mins 67 | 68 | struct eap_header { 69 | uint8_t eapol_v; 70 | uint8_t eapol_t; 71 | uint16_t eapol_length; 72 | uint8_t eap_t; 73 | uint8_t eap_id; 74 | uint16_t eap_length; 75 | uint8_t eap_op; 76 | uint8_t eap_v_length; 77 | uint8_t eap_md5_challenge[16]; 78 | u_char eap_info_tailer[40]; 79 | }; 80 | 81 | enum EAPType { 82 | EAPOL_START, 83 | EAPOL_LOGOFF, 84 | EAP_REQUEST_IDENTITY, 85 | EAP_RESPONSE_IDENTITY, 86 | EAP_REQUEST_IDENTITY_KEEP_ALIVE, 87 | EAP_RESPONSE_IDENTITY_KEEP_ALIVE, 88 | EAP_REQUETS_MD5_CHALLENGE, 89 | EAP_RESPONSE_MD5_CHALLENGE, 90 | EAP_SUCCESS, 91 | EAP_FAILURE, 92 | ERROR, 93 | EAP_NOTIFICATION, 94 | EAP_REQUEST_MD5_KEEP_ALIVE=250 95 | }; 96 | 97 | void YD_identity_transform(); 98 | void send_eap_packet(enum EAPType send_type); 99 | void show_usage(); 100 | char* get_md5_digest(const char* str, size_t len); 101 | void action_by_eap_type(enum EAPType pType, 102 | const struct eap_header *header, 103 | const struct pcap_pkthdr *packetinfo, 104 | const uint8_t *packet); 105 | void send_eap_packet(enum EAPType send_type); 106 | void init_frames(); 107 | void init_info(); 108 | void init_device(); 109 | void init_arguments(int *argc, char ***argv); 110 | int set_device_new_ip(); 111 | void fill_password_md5(uint8_t attach_key[], uint8_t eap_id); 112 | void fill_uname_md5(uint8_t attach_key[], uint8_t eap_id); 113 | int program_running_check(); 114 | void daemon_init(void); 115 | void show_local_info(); 116 | void print_server_info (const uint8_t *packet, uint16_t packetlength); 117 | int code_convert(char *from_charset, char *to_charset, 118 | char *inbuf, size_t inlen, char *outbuf, size_t outlen); 119 | void printNotification(const struct eap_header *eap_header); 120 | void time_out_handler(); 121 | unsigned int generateRandomPort(); 122 | void print_hex(uint8_t *array, int count); 123 | void DrcomAuthenticationEntry(); 124 | void get_packet(uint8_t *args, const struct pcap_pkthdr *header,const uint8_t *packet); 125 | 126 | 127 | --------------------------------------------------------------------------------