-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmentohust.c
256 lines (247 loc) · 7.2 KB
/
mentohust.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/* -*- Mode: C; tab-width: 4; -*- */
/*
* Copyright (C) 2009, HustMoon Studio
*
* 文件名称:mentohust.c
* 摘 要:MentoHUST主函数
* 作 者:HustMoon@BYHH
* 邮 箱:[email protected]
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "myconfig.h"
#include "i18n.h"
#include "mystate.h"
#include "myfunc.h"
#include "dlfunc.h"
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
extern pcap_t *hPcap;
extern volatile int state;
extern u_char *fillBuf;
extern const u_char *capBuf;
extern unsigned startMode, dhcpMode, maxFail;
extern u_char destMAC[];
extern int lockfd;
#ifndef NO_NOTIFY
extern int showNotify;
#endif
#ifndef NO_ARP
extern u_int32_t rip, gateway;
extern u_char gateMAC[];
#endif
static void exit_handle(void); /* 退出回调 */
static void sig_handle(int sig); /* 信号回调 */
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf); /* pcap_loop回调 */
static void showRuijieMsg(const u_char *buf, unsigned bufLen); /* 显示锐捷服务器提示信息 */
static void showCernetMsg(const u_char *buf); /* 显示赛尔服务器提示信息 */
int main(int argc, char **argv)
{
#ifdef ENABLE_NLS
textdomain(GETTEXT_PACKAGE);
setlocale(LC_ALL, "");
#endif
atexit(exit_handle);
initConfig(argc, argv);
signal(SIGALRM, sig_handle); /* 定时器 */
signal(SIGHUP, sig_handle); /* 注销时 */
signal(SIGINT, sig_handle); /* Ctrl+C */
signal(SIGQUIT, sig_handle); /* Ctrl+\ */
signal(SIGTSTP, sig_handle); /* Ctrl+Z */
signal(SIGTERM, sig_handle); /* 被结束时 */
if (dhcpMode == 3) /* 认证前DHCP */
switchState(ID_DHCP);
else
switchState(ID_START); /* 开始认证 */
if (-1 == pcap_loop(hPcap, -1, pcap_handle, NULL)) { /* 开始捕获数据包 */
printf(_("!! 捕获数据包失败,请检查网络连接!\n"));
#ifndef NO_NOTIFY
if (showNotify && show_notify(_("MentoHUST - 错误提示"),
_("捕获数据包失败,请检查网络连接!"), 1000*showNotify) < 0)
showNotify = 0;
#endif
}
exit(EXIT_FAILURE);
}
static void exit_handle(void)
{
if (state != ID_DISCONNECT)
switchState(ID_DISCONNECT);
if (hPcap != NULL)
pcap_close(hPcap);
if (fillBuf != NULL)
free(fillBuf);
if (lockfd > -1)
close(lockfd);
#ifndef NO_NOTIFY
free_libnotify();
#endif
#ifndef NO_DYLOAD
free_libpcap();
#endif
printf(_(">> 认证已退出。\n"));
}
static void sig_handle(int sig)
{
if (sig == SIGALRM) /* 定时器 */
{
if (-1 == switchState(state))
{
pcap_breakloop(hPcap);
printf(_("!! 发送数据包失败, 请检查网络连接!\n"));
#ifndef NO_NOTIFY
if (showNotify && show_notify(_("MentoHUST - 错误提示"),
_("发送数据包失败, 请检查网络连接!"), 1000*showNotify) < 0)
showNotify = 0;
#endif
exit(EXIT_FAILURE);
}
}
else /* 退出 */
{
pcap_breakloop(hPcap);
exit(EXIT_SUCCESS);
}
}
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf)
{
static unsigned failCount = 0;
#ifndef NO_ARP
if (buf[0x0c]==0x88 && buf[0x0d]==0x8e) {
#endif
if (memcmp(destMAC, buf+6, 6)!=0 && startMode>2) /* 服务器MAC地址不符 */
return;
capBuf = buf;
if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x01) { /* 验证用户名 */
if (startMode < 3) {
memcpy(destMAC, buf+6, 6);
printf(_("** 认证MAC:\t%s\n"), formatHex(destMAC, 6));
startMode += 3; /* 标记为已获取 */
}
if (startMode==3 && memcmp(buf+0x17, "User name", 9)==0) /* 塞尔 */
startMode = 5;
switchState(ID_IDENTITY);
}
else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x04) /* 验证密码 */
switchState(ID_CHALLENGE);
else if (buf[0x0F]==0x00 && buf[0x12]==0x03) { /* 认证成功 */
printf(_(">> 认证成功!\n"));
failCount = 0;
if (!(startMode%3 == 2)) {
getEchoKey(buf);
showRuijieMsg(buf, h->caplen);
}
if (dhcpMode==1 || dhcpMode==2) /* 二次认证第一次或者认证后 */
switchState(ID_DHCP);
else if (startMode%3 == 2)
switchState(ID_WAITECHO);
else
switchState(ID_ECHO);
}
else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x02) /* 显示赛尔提示信息 */
showCernetMsg(buf);
else if (buf[0x0F] == 0x05) /* (赛尔)响应在线 */
switchState(ID_ECHO);
else if (buf[0x0F]==0x00 && buf[0x12]==0x04) { /* 认证失败或被踢下线 */
if (state==ID_WAITECHO || state==ID_ECHO) {
printf(_(">> 认证掉线,开始重连!\n"));
switchState(ID_START);
}
else if (buf[0x1b]!=0 || startMode%3==2) {
printf(_(">> 认证失败!\n"));
if (startMode%3 != 2)
showRuijieMsg(buf, h->caplen);
if (maxFail && ++failCount>=maxFail) {
printf(_(">> 连续认证失败%u次,退出认证。\n"), maxFail);
exit(EXIT_SUCCESS);
}
restart();
}
else
switchState(ID_START);
}
#ifndef NO_ARP
} else if (gateMAC[0]!=0xFE && buf[0x0c]==0x08 && buf[0x0d]==0x06) {
if (*(u_int32_t *)(buf+0x1c) == gateway) {
char str[50];
if (gateMAC[0] == 0xFF) {
memcpy(gateMAC, buf+0x16, 6);
printf(_("** 网关MAC:\t%s\n"), formatHex(gateMAC, 6));
sprintf(str, "arp -s %s %s", formatIP(gateway), formatHex(gateMAC, 6));
system(str);
} else if (buf[0x15]==0x02 && *(u_int32_t *)(buf+0x26)==rip
&& memcmp(gateMAC, buf+0x16, 6)!=0) {
printf(_("** ARP欺骗:\t%s\n"), formatHex(buf+0x16, 6));
#ifndef NO_NOTIFY
if (showNotify) {
sprintf(str, _("欺骗源: %s"), formatHex(buf+0x16, 6));
if (show_notify(_("MentoHUST - ARP提示"), str, 1000*showNotify) < 0)
showNotify = 0;
}
#endif
}
}
}
#endif
}
static void showRuijieMsg(const u_char *buf, unsigned bufLen)
{
char *serverMsg;
int length = buf[0x1b];
if (length > 0) {
for (serverMsg=(char *)(buf+0x1c); *serverMsg=='\r'||*serverMsg=='\n'; serverMsg++,length--); /* 跳过开头的换行符 */
if (strlen(serverMsg) < length)
length = strlen(serverMsg);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL) {
if (strlen(serverMsg)) {
printf(_("$$ 系统提示:\t%s\n"), serverMsg);
#ifndef NO_NOTIFY
if (showNotify && show_notify(_("MentoHUST - 系统提示"),
serverMsg, 1000*showNotify) < 0)
showNotify = 0;
#endif
}
free(serverMsg);
}
}
if ((length=0x1c+buf[0x1b]+0x69+39) < bufLen) {
serverMsg=(char *)(buf+length);
if (buf[length-1]-2 > bufLen-length)
length = bufLen - length;
else
length = buf[length-1]-2;
for (; *serverMsg=='\r'||*serverMsg=='\n'; serverMsg++,length--);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL) {
if (strlen(serverMsg)) {
printf(_("$$ 计费提示:\t%s\n"), serverMsg);
#ifndef NO_NOTIFY
if (showNotify && show_notify(_("MentoHUST - 计费提示"),
serverMsg, 1000*showNotify) < 0)
showNotify = 0;
#endif
}
free(serverMsg);
}
}
}
static void showCernetMsg(const u_char *buf)
{
char *serverMsg = (char *)(buf+0x17);
int length = ntohs(*(u_int16_t *)(buf+0x14)) - 5;
if (strlen(serverMsg) < length)
length = strlen(serverMsg);
if (length>0 && (serverMsg=gbk2utf(serverMsg, length))!=NULL)
{
printf(_("$$ 系统提示:\t%s\n"), serverMsg);
#ifndef NO_NOTIFY
if (showNotify && show_notify(_("MentoHUST - 系统提示"),
serverMsg, 1000*showNotify) < 0)
showNotify = 0;
#endif
free(serverMsg);
}
}