├── 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 |
--------------------------------------------------------------------------------