int main(int argc, char **argv) { atexit(exit_handle); if(initConfig(argc, argv)) exit(EXIT_FAILURE); 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); /* 被结束时 */ signal(SIGKILL, 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 - 错误提示", "捕获数据包失败,请检查网络连接!"); #endif } exit(EXIT_FAILURE); }
static void* lan_thread() { if (-1 == pcap_loop(hPcapLan, -1, pcap_handle_lan, NULL)) { /* 开始捕获数据包 */ print_log(_("!! 从LAN捕获数据包失败,请检查网络连接!\n")); #ifndef NO_NOTIFY if (showNotify && show_notify(_("MentoHUST - 错误提示"), _("!! 从LAN捕获数据包失败,请检查网络连接!\n"), 1000*showNotify) < 0) showNotify = 0; #endif } return 0; }
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)) { print_log(_("$$ 系统提示:\n%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)) { print_log(_("$$ 计费提示:\n%s\n"), serverMsg); #ifndef NO_NOTIFY if (showNotify && show_notify(_("MentoHUST - 计费提示"), serverMsg, 1000*showNotify) < 0) showNotify = 0; #endif } free(serverMsg); } } }
static void* wan_thread() { char* err_base[2] = { _("!! 捕获数据包失败,请检查网络连接!\n"), _("!! 从WAN捕获数据包失败,请检查网络连接!\n") }; if (-1 == pcap_loop(hPcap, -1, pcap_handle, NULL)) { /* 开始捕获数据包 */ print_log("%s", err_base[proxyMode == 1]); #ifndef NO_NOTIFY if (showNotify && show_notify(_("MentoHUST - 错误提示"), err_base[proxyMode == 1], 1000*showNotify) < 0) showNotify = 0; #endif } return 0; }
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); #endif free(serverMsg); } fflush(stdout); }
static void sig_handle(int sig) { if (sig == SIGALRM) /* 定时器 */ { if (-1 == switchState(state)) { pcap_breakloop(hPcap); printf("!! 发送数据包失败, 请检查网络连接!\n"); fflush(stdout); #ifndef NO_NOTIFY if (showNotify) show_notify("MentoHUST - 错误提示", "发送数据包失败, 请检查网络连接!"); #endif exit(EXIT_FAILURE); } } else /* 退出 */ { pcap_breakloop(hPcap); exit(EXIT_SUCCESS); } }
static void sig_handle(int sig) { if (sig == SIGALRM) /* 定时器 */ { if (-1 == switchState(state)) { pcap_breakloop(hPcap); print_log(_("!! 发送数据包失败, 请检查网络连接!\n")); #ifndef NO_NOTIFY if (showNotify && show_notify(_("MentoHUST - 错误提示"), _("发送数据包失败, 请检查网络连接!"), 1000*showNotify) < 0) showNotify = 0; #endif exit(EXIT_FAILURE); } } else /* 退出 */ { print_log(_("!! 收到信号:%s (%d)\n"), strsignal(sig), sig); pcap_breakloop(hPcap); if (hPcapLan != NULL) pcap_breakloop(hPcapLan); 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"); fflush(stdout); 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"); fflush(stdout); switchState(ID_START); } else if (buf[0x1b]!=0 || startMode%3==2) { printf("!! 认证失败!\n"); fflush(stdout); if (startMode%3 != 2) showRuijieMsg(buf, h->caplen); if (maxFail && ++failCount>=maxFail) { printf(">! 连续认证失败%u次,退出认证。\n", maxFail); fflush(stdout); 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)); fflush(stdout); 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)); fflush(stdout); #ifndef NO_NOTIFY if (showNotify) { sprintf(str, "欺骗源: %s", formatHex(buf+0x16, 6)); show_notify("MentoHUST - ARP提示", str); } #endif } } } #endif }
static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf) { static unsigned failCount = 0; pthread_t thread_lan; #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); print_log(_("** 认证服务器MAC: %s\n"), formatHex(destMAC, 6)); startMode += 3; /* 标记认证服务器MAC为已获取,可以锁定 */ } if (proxyMode == 0) { if (startMode==3 && memcmp(buf+0x17, "User name", 9)==0) /* 塞尔 */ startMode = 5; switchState(ID_IDENTITY); } else { if (proxyClientRequested == 1) { print_log(_(">> 服务器已请求用户名\n")); proxy_send_to_lan(buf, h->len); } else { print_log(_("!! 在代理认证完成后收到用户名请求,将重启认证!\n")); switchState(ID_WAITCLIENT); } } } else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x04) { /* 验证密码 */ if (proxyMode == 0) { switchState(ID_CHALLENGE); } else { if (proxyClientRequested == 1) { print_log(_(">> 服务器已请求密码\n")); proxy_send_to_lan(buf, h->len); } else { print_log(_("!! 在代理认证完成后收到密码请求,将重启认证!\n")); switchState(ID_WAITCLIENT); } } } else if (buf[0x0F]==0x00 && buf[0x12]==0x03) { /* 认证成功 */ print_log(_(">> 认证成功!\n")); failCount = 0; proxySuccessCount++; if (proxyMode != 0) { proxy_send_to_lan(buf, h->len); if (proxySuccessCount >= proxyRequireSuccessCount) { pcap_breakloop(hPcapLan); proxyClientRequested = 0; proxySuccessCount = 0; memcpy(lastSuccessClientMAC, clientMAC, 6); // 备份本次认证成功的客户端MAC,用于通知掉线 proxy_clear_client_mac(); // 重设MAC地址,以备下次使用不同客户端认证用 print_log(_(">> 已关闭LAN监听线程\n")); } } 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) { if (proxyMode == 0) { print_log(_(">> 认证掉线!\n")); showRuijieMsg(buf, h->caplen); if (restartOnLogOff) { print_log(_(">> 正在重新认证...\n")); switchState(ID_START); } else { exit(1); } } else { pthread_create(&thread_lan, NULL, lan_thread, 0); print_log(_(">> 认证掉线,已发回客户端并重新启用对LAN的监听\n")); showRuijieMsg(buf, h->caplen); // clientMAC已经在成功时被清除了,所以使用lastSuccessClientMAC发送,发完清除 memmove(clientMAC, lastSuccessClientMAC, 6); proxy_send_to_lan(buf, h->len); proxy_clear_client_mac(); switchState(ID_WAITCLIENT); } } else if (buf[0x1b]!=0 || startMode%3==2) { print_log(_(">> 认证失败!\n")); showRuijieMsg(buf, h->caplen); if (maxFail && ++failCount>=maxFail) { print_log(_(">> 连续认证失败%u次,退出认证。\n"), maxFail); exit(EXIT_SUCCESS); } restart(); } else { if (proxyMode == 0) switchState(ID_START); else switchState(ID_WAITCLIENT); } } #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); print_log(_("** 网关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 && memcmp(&rip, buf+0x26, 4)==0 && memcmp(gateMAC, buf+0x16, 6)!=0) { print_log(_("** 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 }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { HINTERNET inet = InternetOpen( "ChewingUpdate", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if( !inet ) return -1; _tcscpy( url_file_name, "version-info" ); HINTERNET ifile = InternetOpenUrl( inet, url, NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0 ); if( ifile ) { char buf[4096]; memset( buf, 0, sizeof(buf) ); char* pbuf = buf; char* end = buf + sizeof(buf); DWORD len = 0; while( InternetReadFile( ifile, pbuf, int(end - pbuf), &len) && len ) { pbuf += len; } InternetCloseHandle(ifile); // version-info should in following simple format: // 1st line: Version string (required) // 2nd line: Release date (required) // 3rd line: URL of relating web page (required) // 4th line to end of file: Change log (optional) if ( strncmp(buf, CSig, strlen(CSig))!=0 ) { return -1; } version = strtok(buf, "\r\n "); if( ! version ) return -1; version += strlen(CSig); // Check if we are using the latest version HKEY hk = NULL; char cur_ver[32] = ""; if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\New Chewing IM"), &hk) ) { DWORD size = sizeof(cur_ver); DWORD type = REG_SZ; RegQueryValueEx( hk, "DisplayVersion", 0, &type, (LPBYTE)cur_ver, &size ); RegCloseKey( hk ); } has_new_version = strcmp( cur_ver, version ) ? true : false; // No new version and in silent mode if( ! has_new_version && strstr(lpCmdLine, "/silent") ) return 0; released_time = strtok( NULL, "\r\n" ); news_url = strtok( NULL, "\r\n" ); change_log = strtok( NULL, "" ); hinst = hInstance; show_notify(); return 0; } InternetCloseHandle(inet); return (ifile ? 0 : -1); }