diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b05750a --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +程序编写 + HustMoon form HUST + kkHAIKE from XTU + +编译脚本 + Microcai from ZSTU + +deb包脚本 + Cheese Lee from SYSU + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..27bfa2e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = src + +dist_doc_DATA = README + +dist_man_MANS = mentohust.1 + +SPEC = mentohust.spec + +EXTRA_DIST = $(SPEC) debian/changelog debian/compat debian/control debian/copyright debian/rules debian/watch + +rpm: dist-gzip + mkdir -p ~/rpmbuild/SOURCES/ + mv mentohust-*.tar.gz ~/rpmbuild/SOURCES/ + if [ -z "$(TARGET)" ] ;then \ + rpmbuild -bb $(top_srcdir)/$(SPEC) ; \ + else rpmbuild -bb $(top_srcdir)/$(SPEC) --target=$(TARGET) ; fi + mv ~/rpmbuild/RPMS/*$(TARGET)/mentohust-*$(TARGET).rpm ./ + rm ~/rpmbuild/SOURCES/mentohust* + +deb: debian/rules + dpkg-buildpackage -rfakeroot -uc -b -d diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..30b33e0 --- /dev/null +++ b/README @@ -0,0 +1,34 @@ +#使用方法 + +#安装mentohust:建议Ubuntu用户使用Deb包安装,Fedora用户使用RPM包安装 + +#如果确定自己可以使用xrgsu认证成功,打开终端输入sudo mentohust运行即可 +#如果不确定,切换到锐捷所在目录,然后输入以下命令: +sudo mkdir /etc/mentohust +sudo cp ./8021x.exe /etc/mentohust +#如果准确按以上步骤操作后还是认证失败,请下载MentoHUSTTool,在Windows下抓包并保存为data.mpf, +然后回到Linux,切换到data.mpf所在目录,输入以下命令: +sudo cp ./data.mpf /etc/mentohust +然后打开终端输入sudo mentohust -f/etc/mentohust/data.mpf -w运行即可。以后也只需输入sudo mentohust。 + +#如何退出:不以后台模式运行mentohust时,按Ctrl+C即可退出;后台运行时使用sudo mentohust -k退出认证。 + +#查看帮助信息请输入:mentohust -h +更详细的帮助信息请参考:http://wiki.ubuntu.org.cn/锐捷、赛尔认证MentoHUST + +#修改参数请根据帮助信息操作,例如修改用户名和密码:sudo mentohust -uUsername -pPassword -w +指定某些参数仅对当次认证有效请根据帮助信息操作,例如临时修改用户名和密码:sudo mentohust -uUsername -pPassword + +#如果提示缺少libpcap.so.0.x而在/usr/lib/目录下已存在一个libpcap.so.0.x.y,输入以下命令: +sudo ln -s libpcap.so.0.x.y /usr/lib/libpcap.so.0.x +否则请安装libpcap。 + +#权责声明 +1、本程序所有涉及锐捷赛尔认证的功能均是来自前辈公开代码及抓包分析。 +2、本程序于个人仅供学习,于他人仅供方便认证,不得使用本程序有意妨害锐捷赛尔认证机制及相关方利益。 +3、一切使用后果由用户自己承担。 +4、本程序不提供任何服务及保障,编写及维护纯属个人爱好,随时可能被终止。 +5、使用本程序者,即表示同意该声明。谢谢合作。 + +源码可在项目主页获取:http://mentohust.googlecode.com/ +联系作者:在http://mentohust.googlecode.com/留言或Email:mentohust@ehust.co.cc diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..10e0f78 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,8 @@ +#! /bin/sh + +set -x + +aclocal +autoheader +automake --add-missing +autoconf diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..7a6db40 --- /dev/null +++ b/configure.ac @@ -0,0 +1,64 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.63]) +AC_INIT([mentohust], [0.3.1], [http://code.google.com/p/mentohust/issues/list]) +AC_CANONICAL_HOST +AM_INIT_AUTOMAKE +AC_CONFIG_SRCDIR([src/myconfig.h]) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AS_IF([test "x$prefix" = "xNONE"], [prefix="/usr"]) +AC_ARG_ENABLE([debug], [AC_HELP_STRING([ --enable-debug], [Build a debug version])], + [CFLAGS="$CFLAGS -g -O0 -DDEBUG -Wall"], + [CFLAGS="$CFLAGS -Os -Wall"]) + +AC_PROG_CC +AC_C_BIGENDIAN + +AC_ARG_ENABLE([encodepass], [AC_HELP_STRING([ --disable-encodepass], [Don't encode password])], + [], [enable_encodepass="yes"]) +AS_IF([test "x$enable_encodepass" = "xno"], + [AC_DEFINE(NO_ENCODE_PASS, [], [Define NO_ENCODE_PASS to disable encoding password])]) + +AC_ARG_ENABLE([arp], [AC_HELP_STRING([ --disable-arp], [Don't care ARP info])], + [], [enable_arp="yes"]) +AS_IF([test "x$enable_arp" = "xno"], + [AC_DEFINE(NO_ARP, [], [Define NO_ARP to disable careing ARP])]) + +# Checks for libraries. +AS_CASE([$host_os], + [*darwin*], + [AC_DEFINE(MAC_OS, [], [Define MAC_OS when compiling for Mac OS]) + AC_CHECK_LIB([iconv], [iconv])]) + +AC_ARG_WITH([pcap], [AC_HELP_STRING([ --with-pcap=TYPE], [How to link libpcap: dyload(Default) | dylib | stlib | PATH])], + [], [with_pcap="dyload"]) +AS_IF([test "x$with_pcap" = "xyes" || test -z "$with_pcap"], [with_pcap="dyload"]) +AS_IF([test "$with_pcap" = "dyload"], [AC_CHECK_LIB([dl], [dlsym])], + [AC_DEFINE(NO_DYLOAD, [], [Define NO_DYLOAD when not load libpcap dynamicly]) + AS_CASE([$with_pcap], + [dylib], [AC_CHECK_LIB([pcap], [pcap_sendpacket])], + [stlib], [AC_SUBST(LDADD, libpcap.a)], + [AC_SUBST(LDADD, "$with_pcap")])]) + +AC_ARG_ENABLE([notify], [AC_HELP_STRING([ --disable-notify], [Don't show notification])], + [], [enable_notify="yes"]) +AS_IF([test "x$enable_notify" = "xno"], + [AC_DEFINE(NO_NOTIFY, [], [Define NO_NOTIFY to disable notification])], + [AC_CHECK_LIB([dl], [dlsym])]) + +# Checks for header files. +AC_CHECK_HEADERS([iconv.h arpa/inet.h fcntl.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_CHECK_FUNCS([atexit memmove memset socket strrchr]) + +AC_CONFIG_FILES([Makefile src/Makefile]) + +AC_MSG_RESULT([config result: host($host_os) pcap($with_pcap) notify($enable_notify) encode($enable_encodepass) arp($enable_arp)]) +AC_OUTPUT diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..0fe13c9 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,41 @@ +mentohust (0.3.1-1) karmic; urgency=low + + * new upstream release. + * add a manpage. + + -- HustMoon Thu, 03 Dec 2009 21:26:15 +0800 + +mentohust (0.3.0-1) karmic; urgency=low + + * new upstream release. + * debian/control: remove libpcap0.8-dev from Build-Depends. + * debian/control: change libpcap0.8 to libpcap0.8 | libpcap0.9 | libpcap1.0 | libpcap1.1 in Depends. + + -- HustMoon Thu, 12 Nov 2009 14:42:15 +0800 + +mentohust (0.2.5-0~r1) karmic; urgency=low + + * New upstream release + * Moved the executable from /usr/sbin/ to /usr/bin/ + + -- Cheese Lee Wed, 04 Nov 2009 16:07:18 +0800 + +mentohust (0.2.4-0~r3) karmic; urgency=low + + * Changed versioning suffix + * Purged some empty files + * Renamed the executable to lowercases + + -- Cheese Lee Fri, 30 Oct 2009 10:50:03 +0800 + +mentohust (0.2.4-0~ppa2) karmic; urgency=low + + * Depend on libpcap0.8 without version + + -- Cheese Lee Thu, 29 Oct 2009 16:24:20 +0800 + +mentohust (0.2.4-0~ppa1) karmic; urgency=low + + * Initial release + + -- Cheese Lee Tue, 27 Oct 2009 19:44:51 +0800 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..a827647 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: mentohust +Section: net +Priority: optional +Maintainer: HustMoon +Build-Depends: debhelper (>= 7), autotools-dev +Standards-Version: 3.8.1 +Homepage: http://code.google.com/p/mentohust/ + +Package: mentohust +Architecture: any +Depends: libpcap0.8 | libpcap0.9 | libpcap1.0 | libpcap1 +Description: A Ruijie and Cernet supplicant on Linux and MacOS from HustMoon Studio + See /usr/share/doc/mentohust/README for more information. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f8ecc74 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,29 @@ +This package was debianized by HustMoon on +Thu, 03 Dec 2009 21:26:15 +0800. + +It was downloaded from http://code.google.com/p/mentohust/downloads/list + +Upstream Authors: + + HustMoon Studio + +Copyright: + + Copyright (C) 2009 HustMoon Studio + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 3. + + On Debian systems, the complete text of the GNU General Public License + can be found in `/usr/share/common-licenses/GPL-3'. + +The Debian packaging is: + + Copyright (C) 2009 Cheese Lee + Copyright (C) 2009 HustMoon + +and is licensed under the GPL version 3, +see `/usr/share/common-licenses/GPL-3'. + diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..500b75d --- /dev/null +++ b/debian/rules @@ -0,0 +1,105 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) +else +CROSS= --build $(DEB_BUILD_GNU_TYPE) +endif + + + +config.status: configure + dh_testdir + # Add here commands to configure the package. +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" + + +build: build-stamp + +#build-stamp: config.status +build-stamp: + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/mentohust.sgml > mentohust.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + #[ ! -f Makefile ] || $(MAKE) distclean + #rm -f config.sub config.guess + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + # Add here commands to install the package into debian/mentohust. + $(MAKE) DESTDIR=$(CURDIR)/debian/mentohust install + +# Build architecture-independent files here. +binary-indep: install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: install + dh_testdir + dh_testroot + dh_installchangelogs # ChangeLog + dh_installdocs +# dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo +# dh_installman +# dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb +# dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..85eabd2 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +version=3 +http://code.google.com/p/mentohust/downloads/list \ + http://mentohust.googlecode.com/files/mentohust-(.*).tar.gz diff --git a/mentohust.1 b/mentohust.1 new file mode 100644 index 0000000..f8eccd5 --- /dev/null +++ b/mentohust.1 @@ -0,0 +1,35 @@ +.\" This file is distributed under the same license as the mentohust package. +.\" Copyright (C) 2009 HustMoon . +.\" +.TH MENTOHUST 1 "2009-12-03" + +.SH NAME +mentohust \- A Ruijie and Cernet supplicant on Linux and MacOS + +.SH SYNOPSIS +.B mentohust +[-option][value] ... + +.SH DESCRIPTION +.PP +mentohust is a Ruijie and Cernet supplicant on Linux and MacOS. +.br +See \fI/usr/share/doc/mentohust/README\fR for more information. + +.PP +Type +.B mentohust -h +and see \fI/usr/share/doc/mentohust/README\fR for usage. + +.PP +Homepage: http://mentohust.googlecode.com/ +.br +E-mail: mentohust@ehust.co.cc + +.SH AUTHOR +.PP +mentohust was written by HustMoon +.br +and kkHAIKE . +.br +This manual page was written by HustMoon . diff --git a/mentohust.spec b/mentohust.spec new file mode 100644 index 0000000..0fcfddb --- /dev/null +++ b/mentohust.spec @@ -0,0 +1,51 @@ +Name: mentohust +Version: 0.3.1 +Release: 1%{?dist} +Summary: A Ruijie and Cernet supplicant +Summary(zh_CN.UTF-8): 锐捷和塞尔认证 + +Group: Applications/Internet +License: BSD +URL: http://code.google.com/p/mentohust/ +Source0: http://mentohust.googlecode.com/files/mentohust-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: glibc-devel +Requires: libpcap + +%description +This package contains a Ruijie and Cernet supplicant from HustMoon Studio. + +See %{_defaultdocdir}/%{name}-%{version}/README for more information. + +%description -l zh_CN.UTF-8 +mentohust是用来进行锐捷和塞尔认证的。因为官方没有Linux版本或者Linux版本很不好用 +^_^ + +详见 %{_defaultdocdir}/%{name}-%{version}/README + + +%prep +%setup -q + + +%build +%configure --docdir=%{_defaultdocdir}/%{name}-%{version} +make %{?_smp_mflags} + + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%{_bindir}/mentohust +%config %{_sysconfdir}/mentohust.conf +%{_mandir}/man1/mentohust* +%doc %{_defaultdocdir}/%{name}-%{version}/* + +%changelog diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..d158e9c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS = mentohust + +sysconfdir = /etc + +dist_sysconf_DATA = mentohust.conf + +mentohust_SOURCES = myini.c md5.c mycheck.c dlfunc.c myfunc.c mystate.c myconfig.c mentohust.c + +mentohust_SOURCES += types.h myini.h md5.h mycheck.h dlfunc.h myfunc.h mystate.h myconfig.h + +mentohust_LDADD = $(LDADD) + diff --git a/src/dlfunc.c b/src/dlfunc.c new file mode 100644 index 0000000..21433bb --- /dev/null +++ b/src/dlfunc.c @@ -0,0 +1,153 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:dlfunc.c +* 摘 要:动态载入库函数 +* 作 者:HustMoon@BYHH +* 邮 箱:www.ehust@gmail.com +* 日 期:2009.11.11 +*/ +#include "dlfunc.h" + +#ifndef NO_DYLOAD +#include + +int (*pcap_findalldevs)(pcap_if_t **, char *); +void (*pcap_freealldevs)(pcap_if_t *); +pcap_t *(*pcap_open_live)(const char *, int, int, int, char *); +int (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); +int (*pcap_setfilter)(pcap_t *, struct bpf_program *); +char *(*pcap_geterr)(pcap_t *); +void (*pcap_freecode)(struct bpf_program *); +int (*pcap_loop)(pcap_t *, int, pcap_handler, unsigned char *); +void (*pcap_close)(pcap_t *); +void (*pcap_breakloop)(pcap_t *); +int (*pcap_sendpacket)(pcap_t *, const unsigned char *, int); + +static void *libpcap = NULL; + +int load_libpcap(void) { + char *error; +#ifdef MAC_OS + char *file[] = {"libpcap.dylib", "libpcap.A.dylib"}; + int i, count = 2; +#else + char *file[] = {"libpcap.so", "libpcap.so.1", "libpcap.so.1.0", "libpcap.so.0.9", "libpcap.so.0.8"}; + int i, count = 5; +#endif + for (i=0; i + +typedef void NotifyNotification, GtkWidget, GError; +typedef char gchar; +typedef int gint, gboolean; + +static gboolean (*notify_notification_update)(NotifyNotification *, const gchar *, + const gchar *, const gchar *); +static void (*notify_notification_set_timeout)(NotifyNotification *, gint); +static gboolean (*notify_notification_show)(NotifyNotification *, GError **); + +static void *libnotify = NULL; +static NotifyNotification *notify = NULL; + +int load_libnotify(void) { + char *error; + gboolean (*notify_init)(const char *); + NotifyNotification *(*notify_notification_new)(const gchar *, const gchar *, + const gchar *, GtkWidget *); +#ifdef MAC_OS + char *file[] = {"libnotify.dylib", "libnotify.1.dylib"}; + int i, count = 2; +#else + char *file[] = {"libnotify.so", "libnotify.so.1"}; + int i, count = 2; +#endif + for (i=0; i +#include + +#define PCAP_ERRBUF_SIZE 256 +#define PCAP_IF_LOOPBACK 0x00000001 + +typedef unsigned int bpf_u_int32; +typedef void pcap_t; +typedef struct pcap_if { + struct pcap_if *next; + char *name; + char *description; + void *addresses; + bpf_u_int32 flags; +}pcap_if_t; +struct bpf_program { + unsigned int bf_len; + void *bf_insns; +}; +struct pcap_pkthdr { + struct timeval ts; + bpf_u_int32 caplen; + bpf_u_int32 len; +}; +typedef void (*pcap_handler)(unsigned char *, const struct pcap_pkthdr *, const unsigned char *); + +#ifdef NO_DYLOAD +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); +pcap_t *pcap_open_live(const char *, int, int, int, char *); +int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); +int pcap_setfilter(pcap_t *, struct bpf_program *); +char *pcap_geterr(pcap_t *); +void pcap_freecode(struct bpf_program *); +int pcap_loop(pcap_t *, int, pcap_handler, unsigned char *); +void pcap_close(pcap_t *); +void pcap_breakloop(pcap_t *); +int pcap_sendpacket(pcap_t *, const unsigned char *, int); + +#else +extern int (*pcap_findalldevs)(pcap_if_t **, char *); +extern void (*pcap_freealldevs)(pcap_if_t *); +extern pcap_t *(*pcap_open_live)(const char *, int, int, int, char *); +extern int (*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32); +extern int (*pcap_setfilter)(pcap_t *, struct bpf_program *); +extern char *(*pcap_geterr)(pcap_t *); +extern void (*pcap_freecode)(struct bpf_program *); +extern int (*pcap_loop)(pcap_t *, int, pcap_handler, unsigned char *); +extern void (*pcap_close)(pcap_t *); +extern void (*pcap_breakloop)(pcap_t *); +extern int (*pcap_sendpacket)(pcap_t *, const unsigned char *, int); + +int load_libpcap(void); /* 载入libpcap.so */ +void free_libpcap(void); /* 释放libpcap.so */ + +#endif /* NO_DYLOAD */ + +#ifndef NO_NOTIFY +int load_libnotify(void); /* 载入libnotify.so */ +void free_libnotify(void); /* 释放libnotify.so */ +void set_timeout(int timeout); /* 设置超时间隔 */ +void show_notify(const char *summary, char *body); /* 显示通知:概要、正文 */ +#endif /* NO_NOTIFY */ + +#endif /* HUSTMOON_DLFUNC_H */ + diff --git a/src/md5.c b/src/md5.c new file mode 100644 index 0000000..074e988 --- /dev/null +++ b/src/md5.c @@ -0,0 +1,297 @@ +/* MD5.c - an implementation of md5 algorithm */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ +#include "md5.h" +#include + +/* Constants for MD5Transform routine. */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(UINT4 [4], UCHAR [64]); +static void Encode(UCHAR *, UINT4 *, UINT4); +static void Decode(UINT4 *, UCHAR *, UINT4); + +static UCHAR PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init (MD5_CTX * context) + +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update (MD5_CTX *context, UCHAR *input, UINT4 inputLen) + +{ + UINT4 i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (UINT4)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final (UCHAR digest[16], MD5_CTX *context) +{ + UCHAR bits[8]; + UINT4 index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (UINT4)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (UINT4 state[4],UCHAR block[64]) +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + +*/ + memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (UCHAR). Assumes len is + a multiple of 4. + */ +static void Encode (UCHAR *output, UINT4 *input, UINT4 len) +{ + UINT4 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (UCHAR)(input[i] & 0xff); + output[j+1] = (UCHAR)((input[i] >> 8) & 0xff); + output[j+2] = (UCHAR)((input[i] >> 16) & 0xff); + output[j+3] = (UCHAR)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (UCHAR) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (UINT4 *output, UCHAR *input, UINT4 len) +{ + UINT4 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/*Compute the md5sum (return static-local-variable),whose length is 16 bytes.*/ +UCHAR* ComputeHash(UCHAR* src, UINT4 len) +{ + MD5_CTX context; + static UCHAR digest[16]; + MD5Init(&context); + MD5Update(&context, src, len); + MD5Final(digest, &context); + return digest; +} diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 0000000..7b29a7c --- /dev/null +++ b/src/md5.h @@ -0,0 +1,43 @@ +/* MD5.H - header file for MD5.C */ + +/* +Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software.*/ + +#ifndef MD5_H +#define MD5_H +#include "types.h" + +/* MD5 context. */ +typedef struct +{ + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + UCHAR buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init(MD5_CTX * context); +void MD5Update(MD5_CTX *context, UCHAR *input, UINT4 inputLen); +void MD5Final(UCHAR digest[16], MD5_CTX *context); + +UCHAR* ComputeHash(UCHAR *src, UINT4 len); + +#endif /* MD5_H */ diff --git a/src/mentohust.c b/src/mentohust.c new file mode 100644 index 0000000..38ae9e0 --- /dev/null +++ b/src/mentohust.c @@ -0,0 +1,289 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:mentohust.c +* 摘 要:MentoHUST主函数 +* 作 者:HustMoon@BYHH +* 邮 箱:www.ehust@gmail.com +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define HAVE_ICONV_H +#endif + +#include "myconfig.h" +#include "mystate.h" +#include "myfunc.h" +#include "dlfunc.h" +#include +#include +#include +#include +#include + +#ifdef HAVE_ICONV_H +#include +#endif + +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) +{ + 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 - 错误提示", "捕获数据包失败,请检查网络连接!"); +#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 - 错误提示", "发送数据包失败, 请检查网络连接!"); +#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)); + 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 +} + +#ifndef MAC_OS +static char *gbk2utf(char *src, size_t srclen) /* GBK转UTF-8 */ +#else +static char *gbk2utf(const char *src, size_t srclen) /* GBK转UTF-8 */ +#endif +{ +#ifdef HAVE_ICONV_H + /* GBK一汉字俩字节,UTF-8一汉字3字节,二者ASCII字符均一字节 + 所以这样申请是足够的了,要记得释放 */ + size_t dstlen = srclen * 3 / 2 + 1; + size_t left = dstlen; + char *dst, *pdst; + int res; + iconv_t cd = iconv_open("utf-8", "gbk"); + if (cd == (iconv_t)-1) + return NULL; + dst = (char *)malloc(dstlen); + pdst = dst; + res = iconv(cd, &src, &srclen, &pdst, &left); + iconv_close(cd); + if (res == -1) + { + free(dst); + return NULL; + } + dst[dstlen-left] = '\0'; +#else + char *dst = (char *)malloc(srclen+1); + memcpy(dst, src, srclen); + dst[srclen] = '\0'; +#endif + return dst; +} + +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) + { + printf("$$ 系统提示:\t%s\n", serverMsg); +#ifndef NO_NOTIFY + if (showNotify) + show_notify("MentoHUST - 系统提示", serverMsg); +#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) + { + printf("$$ 计费提示:\t%s\n", serverMsg); +#ifndef NO_NOTIFY + if (showNotify) + show_notify("MentoHUST - 计费提示", serverMsg); +#endif + free(serverMsg); + } + } + fflush(stdout); +} + +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); +} diff --git a/src/mentohust.conf b/src/mentohust.conf new file mode 100644 index 0000000..cd294ee --- /dev/null +++ b/src/mentohust.conf @@ -0,0 +1,46 @@ +# MentoHUST for Linux By HustMoon Studio +# +# 配置文件名称必须是小写/etc/mentohust.conf,编码格式建议是UTF-8 +# 配置文件中一行开头的空格和Tab会被忽略,其他的会视为参数一部分 +# 配置文件中Section与Key不区分大小写,以#或;开头的行视为注释 +# 同一个参数若在命令行参数和配置文件中均有设置,使用命令行参数 +# 命令行中使用参数-h或-?可查看详细参数信息,建议通过命令行设置参数 +# 命令行中使用参数-w可将配置更新到/etc/mentohust.conf + +[MentoHUST] +;用户名,长度不超过64 +Username= +;密码(简单加密) +EncodePass= +;网卡 +Nic= +;静态IP用户可以使用非本机IP +IP= +;掩码,无关紧要 +Mask= +;网关,如果指定了就会监视网关ARP信息 +Gateway= +;DNS服务器,无关紧要 +DNS= +;Ping主机,用于掉线检测,0.0.0.0表示关闭该功能 +PingHost= +;每次发包超时时间(秒) +Timeout= +;发送Echo包的间隔(秒) +EchoInterval= +;失败等待(秒)认证失败后等待RestartWait秒或者服务器请求后重启认证 +RestartWait= +;寻找服务器时的组播地址类型 0标准 1锐捷 2将MentoHUST用于赛尔认证 +StartMode= +;DHCP方式 0(不使用) 1(二次认证) 2(认证后) 3(认证前) +DhcpMode= +;是否后台运行: 0(否) 1(是,关闭输出) 2(是,保留输出) 3(是,输出到文件/tmp/mentohust.log) +DaemonMode= +;是否显示通知: 0(否) 1~20(是) +ShowNotify= +;客户端版本号,如果未开启客户端校验但对版本号有要求,可以在此指定,形如3.30 +Version= +;认证数据文件,如果需要校验客户端,就需要正确设置 +DataFile= +;进行DHCP的脚本 +DhcpScript= diff --git a/src/mycheck.c b/src/mycheck.c new file mode 100644 index 0000000..272d8c4 --- /dev/null +++ b/src/mycheck.c @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:mycheck.c +* 摘 要:客户端校验算法 +* 作 者:kkHAIKE & HustMoon +*/ +#include "mycheck.h" +#include "md5.h" +#include +#include +#include + +static BYTE *bin_8021x = NULL; +static DWORD size_8021x; +static BYTE hex[][17]={"0123456789ABCDEF", "0123456789abcdef"}; + +#ifdef WORDS_BIGENDIAN +WORD ltobs(WORD x) { + return ((x & 0xff) << 8) | ((x & 0xff00) >> 8); +} + +DWORD ltobl(DWORD x) { + return ((x & 0xff) << 24) |\ + ((x & 0xff00) << 8) |\ + ((x & 0xff0000) >> 8) |\ + ((x & 0xff000000) >> 24); +} +#endif + +void hex_to_str(const BYTE *a, char *b, int hexsize, int upper) { + BYTE *q = (BYTE *)b; + int i; + for (i=0; i>4]; q++; + *q = hex[upper][a[i]&0xf]; q++; + } + *q = 0; +} + +BYTE *ReadCode(const char *file, DWORD *size) { + BYTE *data = NULL; + int i; + FILE *fp; + PPE_HEADER_MAP hpe; + + if ((fp=fopen(file, "rb")) == NULL) + goto fileError; + data = (BYTE *)malloc(0x1000); + if (fread(data, 0x1000, 1, fp) < 1) + goto fileError; + + hpe = (PPE_HEADER_MAP)(data + LTOBL(((PIMAGE_DOS_HEADER)data)->e_lfanew)); + for (i=0; i_head.NumberOfSections); i++) { + if (LTOBL(hpe->section_header[i].Characteristics) & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) { + fseek(fp, LTOBL(hpe->section_header[i].PointerToRawData), SEEK_SET); + *size = LTOBL(hpe->section_header[i].SizeOfRawData); + free(data); + data = (BYTE *)malloc(*size); + if (fread(data, *size, 1, fp) < 1) + goto fileError; + fclose(fp); + return data; + } + } + +fileError: + if (fp != NULL) + fclose(fp); + if (data != NULL) + free(data); + return NULL; +} + +BYTE *ReadCode2(const char *dataFile, DWORD *size) { + BYTE Buf[16], *buf=Buf; + FILE *fp = NULL; + if ((fp=fopen(dataFile, "rb")) == NULL + || fread(buf, 16, 1, fp ) < 1) + goto fileError; + *size = LTOBL(*(UINT4 *)buf ^ *(UINT4 *)(buf + 4)); + if ((int)*size <= 0) + goto fileError; + buf = (BYTE *)malloc(*size+0x100); + if (fread(buf, *size, 1, fp) < 1) { + free(buf); + goto fileError; + } + fclose(fp); + return buf; + +fileError: + if (fp != NULL) + fclose(fp); + return NULL; +} + +void check_free() { + if (bin_8021x) { + free(bin_8021x); + bin_8021x = NULL; + } +} + +int check_init(const char *dataFile) { + char name[0x100]; + char *p; + check_free(); + strcpy(name, dataFile); + if ((p=strrchr(name, '/')+1) == (void *)1) + p = name; + strcpy(p, "8021x.exe"); + if ((bin_8021x=ReadCode(name, &size_8021x)) == NULL + && (bin_8021x=ReadCode2(dataFile, &size_8021x)) == NULL) + return -1; + return 0; +} + +void V2_check(const BYTE *seed, char *final_str) { + int i, size = size_8021x / 8; + BYTE table[144], *md5Dig, *b8021x = (BYTE *)malloc(size+16); + memcpy(b8021x, seed, 16); + for (i=0; i<8; i++) { + memcpy(b8021x+16, bin_8021x+size*i, size); + md5Dig = ComputeHash(b8021x, size+16); + table[18*i] = seed[2*i]; + memcpy(table+18*i+1, md5Dig, 16); + table[18*i+17] = seed[2*i+1]; + } + free(b8021x); + md5Dig = ComputeHash(table, 144); + hex_to_str(md5Dig, final_str, 16, 1); +} + +DWORD getVer(const char *file) { + FILE *fp; + BYTE *data = NULL; + int i, j; + DWORD size, VirtualAddress; + PPE_HEADER_MAP hpe; + PIMAGE_RESOURCE_DIRECTORY prd; + PIMAGE_RESOURCE_DATA_ENTRY prde; + PVS_VERSIONINFO pvs; + + if ((fp=fopen(file, "rb")) == NULL) + goto fileError; + data = (BYTE *)malloc(0x1000); + if (fread(data, 0x1000, 1, fp) < 1) + goto fileError; + + hpe = (PPE_HEADER_MAP)(data + LTOBL(((PIMAGE_DOS_HEADER)data)->e_lfanew)); + for (i=LTOBS(hpe->_head.NumberOfSections)-1; i>=0; i--) { + if (strcmp(hpe->section_header[i].Name, ".rsrc") == 0) { + fseek(fp, LTOBL(hpe->section_header[i].PointerToRawData), SEEK_SET); + size = LTOBL(hpe->section_header[i].SizeOfRawData); + VirtualAddress = LTOBL(hpe->section_header[i].VirtualAddress); + free(data); + data = (BYTE *)malloc(size); + if (fread(data, size, 1, fp) < 1) + goto fileError; + prd = (PIMAGE_RESOURCE_DIRECTORY)data; + for (j=0; jNumberOfIdEntries); j++) { + prd->DirectoryEntries[j].Name = LTOBL(prd->DirectoryEntries[j].Name); + if (prd->DirectoryEntries[j].Id==16 && prd->DirectoryEntries[j].NameIsString==0) { + prd->DirectoryEntries[j].OffsetToData = LTOBL(prd->DirectoryEntries[j].OffsetToData); + prd = (PIMAGE_RESOURCE_DIRECTORY)(data+prd->DirectoryEntries[j].OffsetToDirectory); + prd->DirectoryEntries[0].OffsetToData = LTOBL(prd->DirectoryEntries[0].OffsetToData); + prd = (PIMAGE_RESOURCE_DIRECTORY)(data+prd->DirectoryEntries[0].OffsetToDirectory); + prde = (PIMAGE_RESOURCE_DATA_ENTRY)(data+LTOBL(prd->DirectoryEntries[0].OffsetToData)); + pvs = (PVS_VERSIONINFO)(data+LTOBL(prde->OffsetToData)-VirtualAddress); + size = pvs->Value.dwFileVersionMS; + fclose(fp); + free(data); + return size; + } + } + goto fileError; + } + } + +fileError: + if (fp != NULL) + fclose(fp); + if (data != NULL) + free(data); + return -1; +} + diff --git a/src/mycheck.h b/src/mycheck.h new file mode 100644 index 0000000..ed51fd3 --- /dev/null +++ b/src/mycheck.h @@ -0,0 +1,219 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:mycheck.h +* 摘 要:客户端校验算法 +* 作 者:kkHAIKE +*/ +#ifndef MYCHECK_H +#define MYCHECK_H + +#include "types.h" + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + WORD e_magic; // Magic number + WORD e_cblp; // Bytes on last page of file + WORD e_cp; // Pages in file + WORD e_crlc; // Relocations + WORD e_cparhdr; // Size of header in paragraphs + WORD e_minalloc; // Minimum extra paragraphs needed + WORD e_maxalloc; // Maximum extra paragraphs needed + WORD e_ss; // Initial (relative) SS value + WORD e_sp; // Initial SP value + WORD e_csum; // Checksum + WORD e_ip; // Initial IP value + WORD e_cs; // Initial (relative) CS value + WORD e_lfarlc; // File address of relocation table + WORD e_ovno; // Overlay number + WORD e_res[4]; // Reserved words + WORD e_oemid; // OEM identifier (for e_oeminfo) + WORD e_oeminfo; // OEM information; e_oemid specific + WORD e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + // + // NT additional fields. + // + + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_SHORT_NAME 8 +typedef struct _IMAGE_SECTION_HEADER { + char Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +typedef struct _PE_HEADER_MAP +{ + DWORD signature; + IMAGE_FILE_HEADER _head; + IMAGE_OPTIONAL_HEADER opt_head; + IMAGE_SECTION_HEADER section_header[8]; +}PE_HEADER_MAP,*PPE_HEADER_MAP; + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { +#ifdef WORDS_BIGENDIAN + union { + struct { + DWORD NameIsString:1; + DWORD NameOffset:31; + }; + DWORD Name; + struct { + WORD Id_unuse; + WORD Id; + }; + }; + union { + DWORD OffsetToData; + struct { + DWORD DataIsDirectory:1; + DWORD OffsetToDirectory:31; + }; + }; +#else + union { + struct { + DWORD NameOffset:31; + DWORD NameIsString:1; + }; + DWORD Name; + WORD Id; + }; + union { + DWORD OffsetToData; + struct { + DWORD OffsetToDirectory:31; + DWORD DataIsDirectory:1; + }; + }; +#endif +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + +typedef struct tagVS_FIXEDFILEINFO { + DWORD dwSignature; /* e.g. 0xfeef04bd */ + DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */ + DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */ + DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */ + DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */ + DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */ + DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */ + DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */ + DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */ + DWORD dwFileType; /* e.g. VFT_DRIVER */ + DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */ + DWORD dwFileDateMS; /* e.g. 0 */ + DWORD dwFileDateLS; /* e.g. 0 */ +} VS_FIXEDFILEINFO; + +typedef struct _VS_VERSIONINFO { + WORD wLength; + WORD wValueLength; + WORD wType; + WORD szKey[16]; + WORD Padding1[1]; + VS_FIXEDFILEINFO Value; +} VS_VERSIONINFO, *PVS_VERSIONINFO; + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable + +#ifdef WORDS_BIGENDIAN +#define LTOBS(x) ltobs(x) +#define LTOBL(x) ltobl(x) +WORD ltobs(WORD x); +DWORD ltobl(DWORD x); +#else +#define LTOBS(x) (x) +#define LTOBL(x) (x) +#endif + +int check_init(const char *dataFile); +void V2_check(const BYTE *seed, char *final_str); +void check_free(); +DWORD getVer(const char *file); + +#endif diff --git a/src/myconfig.c b/src/myconfig.c new file mode 100644 index 0000000..3146c36 --- /dev/null +++ b/src/myconfig.c @@ -0,0 +1,592 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:myconfig.c +* 摘 要:初始化认证参数 +* 作 者:HustMoon@BYHH +* 邮 箱:www.ehust@gmail.com +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +static const char *VERSION = "0.3.1"; +static const char *PACKAGE_BUGREPORT = "http://code.google.com/p/mentohust/issues/list"; +#endif + +#include "myconfig.h" +#include "myini.h" +#include "myfunc.h" +#include "dlfunc.h" +#include +#include +#include +#include +#include +#include + +#define ACCOUNT_SIZE 65 /* 用户名密码长度*/ +#define NIC_SIZE 16 /* 网卡名最大长度 */ +#define MAX_PATH 255 /* FILENAME_MAX */ +#define D_TIMEOUT 8 /* 默认超时间隔 */ +#define D_ECHOINTERVAL 30 /* 默认心跳间隔 */ +#define D_RESTARTWAIT 15 /* 默认重连间隔 */ +#define D_STARTMODE 0 /* 默认组播模式 */ +#define D_DHCPMODE 0 /* 默认DHCP模式 */ +#define D_DAEMONMODE 0 /* 默认daemon模式 */ +#define D_MAXFAIL 0 /* 默认允许失败次数 */ + +static const char *D_DHCPSCRIPT = "dhclient"; /* 默认DHCP脚本 */ +static const char *CFG_FILE = "/etc/mentohust.conf"; /* 配置文件 */ +static const char *LOG_FILE = "/tmp/mentohust.log"; /* 日志文件 */ +static const char *LOCK_FILE = "/var/run/mentohust.pid"; /* 锁文件 */ +#define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* 创建掩码 */ + +#ifndef NO_NOTIFY +#define D_SHOWNOTIFY 5 /* 默认Show Notify模式 */ +int showNotify = D_SHOWNOTIFY; /* 显示通知 */ +#endif + +extern int bufType; /*0内置xrgsu 1内置Win 2仅文件 3文件+校验*/ +extern u_char version[]; /* 版本 */ +char userName[ACCOUNT_SIZE] = ""; /* 用户名 */ +char password[ACCOUNT_SIZE] = ""; /* 密码 */ +char nic[NIC_SIZE] = ""; /* 网卡名 */ +char dataFile[MAX_PATH] = ""; /* 数据文件 */ +char dhcpScript[MAX_PATH] = ""; /* DHCP脚本 */ +u_int32_t ip = 0; /* 本机IP */ +u_int32_t mask = 0; /* 子网掩码 */ +u_int32_t gateway = 0; /* 网关 */ +u_int32_t dns = 0; /* DNS */ +u_int32_t pingHost = 0; /* ping */ +u_char localMAC[6]; /* 本机MAC */ +u_char destMAC[6]; /* 服务器MAC */ +unsigned timeout = D_TIMEOUT; /* 超时间隔 */ +unsigned echoInterval = D_ECHOINTERVAL; /* 心跳间隔 */ +unsigned restartWait = D_RESTARTWAIT; /* 失败等待 */ +unsigned startMode = D_STARTMODE; /* 组播模式 */ +unsigned dhcpMode = D_DHCPMODE; /* DHCP模式 */ +unsigned maxFail = D_MAXFAIL; /* 允许失败次数 */ +pcap_t *hPcap = NULL; /* Pcap句柄 */ +int lockfd = -1; /* 锁文件描述符 */ + +static int readFile(int *daemonMode); /* 读取配置文件来初始化 */ +static void readArg(char argc, char **argv, int *saveFlag, int *exitFlag, int *daemonMode); /* 读取命令行参数来初始化 */ +static void showHelp(const char *fileName); /* 显示帮助信息 */ +static int getAdapter(); /* 查找网卡名 */ +static void printConfig(); /* 显示初始化后的认证参数 */ +static int openPcap(); /* 初始化pcap、设置过滤器 */ +static void saveConfig(int daemonMode); /* 保存参数 */ +static void checkRunning(int exitFlag, int daemonMode); /* 检测是否已运行 */ + +#ifndef NO_ENCODE_PASS +static const unsigned char base64Tab[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}; +static const char xorRuijie[] = {"~!:?$*<(qw2e5o7i8x12c6m67s98w43d2l45we82q3iuu1z4xle23rt4oxclle34e54u6r8m"}; + +static int encodePass(char *dst, const char *osrc) { + unsigned char in[3], buf[70]; + unsigned char *src = buf; + int sz = strlen(osrc); + int i, len; + if (sizeof(xorRuijie) < sz) + return -1; + for(i=0; i 0) { + for (len=0, i=0; i<3; i++, sz--) { + if (sz > 0) { + len++; + in[i] = src[i]; + } else in[i] = 0; + } + src += 3; + if (len) { + dst[0] = base64Tab[ in[0] >> 2 ]; + dst[1] = base64Tab[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; + dst[2] = len > 1 ? base64Tab[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='; + dst[3] = len > 2 ? base64Tab[ in[2] & 0x3f ] : '='; + dst += 4; + } + } + *dst = '\0'; + return 0; +} + +static int decodePass(char *dst, const char *src) { + unsigned esi = 0, idx = 0; + int i=0, j=0, equal=0; + for(; src[i]!='\0'; i++) { + if (src[i] == '=') { + if (++equal > 2) + return -1; + } else { + for(idx=0; base64Tab[idx]!='\0'; idx++) { + if(base64Tab[idx] == src[i]) + break; + } + if (idx == 64) + return -1; + esi += idx; + } + if(i%4 == 3) { + dst[j++] = (char)(esi>>16); + if(equal < 2) + dst[j++] = (char)(esi>>8); + if(equal < 1) + dst[j++] = (char)esi; + esi = 0; + equal = 0; + } + esi <<= 6; + } + if (i%4!=0 || sizeof(xorRuijie)= 3) { + unsigned ver[2]; + if (sscanf(tmp, "%u.%u", ver, ver+1)!=EOF && ver[0]!=0) { + version[0] = ver[0]; + version[1] = ver[1]; + bufType = 1; + } + } + getString(buf, "MentoHUST", "IP", "255.255.255.255", tmp, sizeof(tmp)); + ip = inet_addr(tmp); + getString(buf, "MentoHUST", "Mask", "255.255.255.255", tmp, sizeof(tmp)); + mask = inet_addr(tmp); + getString(buf, "MentoHUST", "Gateway", "0.0.0.0", tmp, sizeof(tmp)); + gateway = inet_addr(tmp); + getString(buf, "MentoHUST", "DNS", "0.0.0.0", tmp, sizeof(tmp)); + dns = inet_addr(tmp); + getString(buf, "MentoHUST", "PingHost", "0.0.0.0", tmp, sizeof(tmp)); + pingHost = inet_addr(tmp); + timeout = getInt(buf, "MentoHUST", "Timeout", D_TIMEOUT) % 100; + echoInterval = getInt(buf, "MentoHUST", "EchoInterval", D_ECHOINTERVAL) % 1000; + restartWait = getInt(buf, "MentoHUST", "RestartWait", D_RESTARTWAIT) % 100; + startMode = getInt(buf, "MentoHUST", "StartMode", D_STARTMODE) % 3; + dhcpMode = getInt(buf, "MentoHUST", "DhcpMode", D_DHCPMODE) % 4; +#ifndef NO_NOTIFY + showNotify = getInt(buf, "MentoHUST", "ShowNotify", D_SHOWNOTIFY) % 21; +#endif + *daemonMode = getInt(buf, "MentoHUST", "DaemonMode", D_DAEMONMODE) % 4; + maxFail = getInt(buf, "MentoHUST", "MaxFail", D_MAXFAIL); + free(buf); + return 0; +} + +static void readArg(char argc, char **argv, int *saveFlag, int *exitFlag, int *daemonMode) +{ + char *str, c; + int i; + for (i=1; i 2) + *exitFlag = 2; + else { + *exitFlag = 1; + return; + } + } else if (strlen(str) > 2) { + if (c == 'u') + strncpy(userName, str+2, sizeof(userName)-1); + else if (c == 'p') + strncpy(password, str+2, sizeof(password)-1); + else if (c == 'n') + strncpy(nic, str+2, sizeof(nic)-1); + else if (c == 'f') + strncpy(dataFile, str+2, sizeof(dataFile)-1); + else if (c == 'c') + strncpy(dhcpScript, str+2, sizeof(dhcpScript)-1); + else if (c=='v' && strlen(str+2)>=3) { + unsigned ver[2]; + if (sscanf(str+2, "%u.%u", ver, ver+1) != EOF) { + if (ver[0] == 0) + bufType = 0; + else { + version[0] = ver[0]; + version[1] = ver[1]; + bufType = 1; + } + } + } + else if (c == 'i') + ip = inet_addr(str+2); + else if (c == 'm') + mask = inet_addr(str+2); + else if (c == 'g') + gateway = inet_addr(str+2); + else if (c == 's') + dns = inet_addr(str+2); + else if (c == 'o') + pingHost = inet_addr(str+2); + else if (c == 't') + timeout = atoi(str+2) % 100; + else if (c == 'e') + echoInterval = atoi(str+2) % 1000; + else if (c == 'r') + restartWait = atoi(str+2) % 100; + else if (c == 'a') + startMode = atoi(str+2) % 3; + else if (c == 'd') + dhcpMode = atoi(str+2) % 4; +#ifndef NO_NOTIFY + else if (c == 'y') + showNotify = atoi(str+2) % 21; +#endif + else if (c == 'b') + *daemonMode = atoi(str+2) % 4; + else if (c == 'l') + maxFail = atoi(str+2); + } + } +} + +static void showHelp(const char *fileName) +{ + char *helpString = + "用法:\t%s [-选项][参数]\n" + "选项:\t-h 显示本帮助信息\n" + "\t-k -k(退出程序) 其他(重启程序)\n" + "\t-w 保存参数到配置文件\n" + "\t-u 用户名\n" + "\t-p 密码\n" + "\t-n 网卡名\n" + "\t-i IP[默认本机IP]\n" + "\t-m 子网掩码[默认本机掩码]\n" + "\t-g 网关[默认0.0.0.0]\n" + "\t-s DNS[默认0.0.0.0]\n" + "\t-o Ping主机[默认0.0.0.0,表示关闭该功能]\n" + "\t-t 认证超时(秒)[默认8]\n" + "\t-e 响应间隔(秒)[默认30]\n" + "\t-r 失败等待(秒)[默认15]\n" + "\t-l 允许失败次数[默认0,表示无限制]\n" + "\t-a 组播地址: 0(标准) 1(锐捷) 2(赛尔) [默认0]\n" + "\t-d DHCP方式: 0(不使用) 1(二次认证) 2(认证后) 3(认证前) [默认0]\n" + "\t-b 是否后台运行: 0(否) 1(是,关闭输出) 2(是,保留输出) 3(是,输出到文件) [默认0]\n" +#ifndef NO_NOTIFY + "\t-y 是否显示通知: 0(否) 1~20(是) [默认5]\n" +#endif + "\t-v 客户端版本号[默认0.00表示兼容xrgsu]\n" + "\t-f 自定义数据文件[默认不使用]\n" + "\t-c DHCP脚本[默认dhclient]\n" + "例如:\t%s -uusername -ppassword -neth0 -i192.168.0.1 -m255.255.255.0 -g0.0.0.0 -s0.0.0.0 -o0.0.0.0 -t8 -e30 -r15 -a0 -d1 -b0 -v4.10 -fdefault.mpf -cdhclient\n" + "注意:使用时请确保是以root权限运行!\n\n"; + printf(helpString, fileName, fileName); + exit(EXIT_SUCCESS); +} + +static int getAdapter() +{ + pcap_if_t *alldevs, *d; + int num = 0, avail = 0, i; + char errbuf[PCAP_ERRBUF_SIZE]; + if (pcap_findalldevs(&alldevs, errbuf)==-1 || alldevs==NULL) + { + printf("!! 查找网卡失败: %s\n", errbuf); + return -1; + } + for (d=alldevs; d!=NULL; d=d->next) + { + num++; + if (!(d->flags & PCAP_IF_LOOPBACK) && strcmp(d->name, "any")!=0) + { + printf("** 网卡[%d]:\t%s\n", num, d->name); + avail++; + i = num; + } + } + if (avail == 0) + { + pcap_freealldevs(alldevs); + printf("!! 找不到网卡!\n"); + return -1; + } + if (avail > 1) + { + printf("?? 请选择网卡[1-%d]: ", num); + scanf("%d", &i); + if (i < 1) + i = 1; + else if (i > num) + i = num; + } + printf("** 您选择了第[%d]块网卡。\n", i); + for (d=alldevs; i>1; d=d->next, i--); + strncpy(nic, d->name, sizeof(nic)-1); + pcap_freealldevs(alldevs); + return 0; +} + +static void printConfig() +{ + char *addr[] = {"标准", "锐捷", "赛尔"}; + char *dhcp[] = {"不使用", "二次认证", "认证后", "认证前"}; + printf("** 用户名:\t%s\n", userName); + /* printf("** 密码:\t%s\n", password); */ + printf("** 网卡: \t%s\n", nic); + if (gateway) + printf("** 网关地址:\t%s\n", formatIP(gateway)); + if (dns) + printf("** DNS地址:\t%s\n", formatIP(dns)); + if (pingHost) + printf("** 智能重连:\t%s\n", formatIP(pingHost)); + printf("** 认证超时:\t%u秒\n", timeout); + printf("** 响应间隔:\t%u秒\n", echoInterval); + printf("** 失败等待:\t%u秒\n", restartWait); + printf("** 允许失败:\t%u次\n", maxFail); + printf("** 组播地址:\t%s\n", addr[startMode]); + printf("** DHCP方式:\t%s\n", dhcp[dhcpMode]); +#ifndef NO_NOTIFY + if (showNotify) + printf("** 通知超时:\t%d秒\n", showNotify); +#endif + if (bufType >= 2) + printf("** 数据文件:\t%s\n", dataFile); + if (dhcpMode != 0) + printf("** DHCP脚本:\t%s\n", dhcpScript); +} + +static int openPcap() +{ + char buf[PCAP_ERRBUF_SIZE], *fmt; + struct bpf_program fcode; + if ((hPcap = pcap_open_live(nic, 2048, 1, 1000, buf)) == NULL) + { + printf("!! 打开网卡%s失败: %s\n", nic, buf); + return -1; + } + fmt = formatHex(localMAC, 6); +#ifndef NO_ARP + sprintf(buf, "((ether proto 0x888e and (ether dst %s or ether dst 01:80:c2:00:00:03)) " + "or ether proto 0x0806) and not ether src %s", fmt, fmt); +#else + sprintf(buf, "ether proto 0x888e and (ether dst %s or ether dst 01:80:c2:00:00:03) " + "and not ether src %s", fmt, fmt); +#endif + if (pcap_compile(hPcap, &fcode, buf, 0, 0xffffffff) == -1 + || pcap_setfilter(hPcap, &fcode) == -1) + { + printf("!! 设置pcap过滤器失败: %s\n", pcap_geterr(hPcap)); + return -1; + } + pcap_freecode(&fcode); + return 0; +} + +static void saveConfig(int daemonMode) +{ + char *buf = loadFile(CFG_FILE); + if (buf == NULL) { + buf = (char *)malloc(1); + buf[0] = '\0'; + } + setString(&buf, "MentoHUST", "DhcpScript", dhcpScript); + setString(&buf, "MentoHUST", "DataFile", dataFile); + if (bufType != 0) { + char ver[10]; + sprintf(ver, "%u.%u", version[0], version[1]); + setString(&buf, "MentoHUST", "Version", ver); + } else + setString(&buf, "MentoHUST", "Version", "0.00"); +#ifndef NO_NOTIFY + setInt(&buf, "MentoHUST", "ShowNotify", showNotify); +#endif + setInt(&buf, "MentoHUST", "DaemonMode", daemonMode); + setInt(&buf, "MentoHUST", "DhcpMode", dhcpMode); + setInt(&buf, "MentoHUST", "StartMode", startMode); + setInt(&buf, "MentoHUST", "MaxFail", maxFail); + setInt(&buf, "MentoHUST", "RestartWait", restartWait); + setInt(&buf, "MentoHUST", "EchoInterval", echoInterval); + setInt(&buf, "MentoHUST", "Timeout", timeout); + setString(&buf, "MentoHUST", "PingHost", formatIP(pingHost)); + setString(&buf, "MentoHUST", "DNS", formatIP(dns)); + setString(&buf, "MentoHUST", "Gateway", formatIP(gateway)); + setString(&buf, "MentoHUST", "Mask", formatIP(mask)); + setString(&buf, "MentoHUST", "IP", formatIP(ip)); + setString(&buf, "MentoHUST", "Nic", nic); +#ifdef NO_ENCODE_PASS + setString(&buf, "MentoHUST", "Password", password); +#else + char pass[ACCOUNT_SIZE*4/3]; + encodePass(pass, password); + setString(&buf, "MentoHUST", "EncodePass", pass); +#endif + setString(&buf, "MentoHUST", "Username", userName); + if (saveFile(buf, CFG_FILE) != 0) + printf("!! 保存认证参数到%s失败!\n", CFG_FILE); + else + printf("** 认证参数已成功保存到%s.\n", CFG_FILE); + free(buf); +} + +static void checkRunning(int exitFlag, int daemonMode) +{ + struct flock fl; + lockfd = open (LOCK_FILE, O_RDWR|O_CREAT, LOCKMODE); + if (lockfd < 0) { + perror("!! 打开锁文件失败"); /* perror真的很好啊,以前没用它真是太亏了 */ + goto error_exit; + } + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_len = 0; + fl.l_type = F_WRLCK; + if (fcntl(lockfd, F_GETLK, &fl) < 0) { + perror("!! 获取文件锁失败"); + goto error_exit; + } + if (exitFlag) { + if (fl.l_type != F_UNLCK) { + printf(">> 已发送退出信号给MentoHUST进程(PID=%d).\n", fl.l_pid); + if (kill(fl.l_pid, SIGINT) == -1) + perror("!! 结束进程失败"); + } + else + printf("!! 没有MentoHUST正在运行!\n"); + if (exitFlag == 1) + exit(EXIT_SUCCESS); + } + else if (fl.l_type != F_UNLCK) { + printf("!! MentoHUST已经运行(PID=%d)!\n", fl.l_pid); + exit(EXIT_FAILURE); + } + if (daemonMode) { /* 貌似我过早进入后台模式了,就给个选项保留输出或者输出到文件吧 */ + printf(">> 进入后台运行模式,使用参数-k可退出认证。\n"); + if (daemon(0, (daemonMode+1)%2)) + perror("!! 后台运行失败"); + else if (daemonMode == 3) { + freopen(LOG_FILE, "w", stdout); + freopen(LOG_FILE, "a", stderr); + } + } + fl.l_type = F_WRLCK; + fl.l_pid = getpid(); + if (fcntl(lockfd, F_SETLKW, &fl) < 0) { + perror("!! 加锁失败"); + goto error_exit; + } + return; + +error_exit: +#ifndef NO_NOTIFY + if (showNotify) + show_notify("MentoHUST - 错误提示", "操作锁文件失败,请检查是否为root权限!"); +#endif + exit(EXIT_FAILURE); +} diff --git a/src/myconfig.h b/src/myconfig.h new file mode 100644 index 0000000..c89a8f8 --- /dev/null +++ b/src/myconfig.h @@ -0,0 +1,13 @@ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:myconfig.h +* 摘 要:初始化认证参数 +* 作 者:HustMoon@BYHH +*/ +#ifndef HUSTMOON_MYCONFIG_H +#define HUSTMOON_MYCONFIG_H + +void initConfig(int argc, char **argv); /* 初始化配置 */ + +#endif diff --git a/src/myfunc.c b/src/myfunc.c new file mode 100644 index 0000000..bea1bfc --- /dev/null +++ b/src/myfunc.c @@ -0,0 +1,522 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:myfunc.c +* 摘 要:认证相关算法及方法 +* 作 者:HustMoon@BYHH +*/ +#include "myfunc.h" +#include "md5.h" +#include "mycheck.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef SIOCGIFHWADDR /* BSD、MacOS */ +#include +#include +#endif +#include + +const u_char STANDARD_ADDR[] = {0x01,0x80,0xC2,0x00,0x00,0x03}; +const u_char RUIJIE_ADDR[] = {0x01,0xD0,0xF8,0x00,0x00,0x03}; +static const char *DATAFILE = "/etc/mentohust/"; /* 默认数据文件(目录) */ + +static int dataOffset; /* 抓包偏移 */ +static u_int32_t echoKey = 0, echoNo = 0; /* Echo阶段所需 */ +u_char *fillBuf = NULL; /* 填充包地址 */ +int fillSize = 0; /* 填充包大小 */ +int bufType = 0; /*0内置xrgsu 1内置Win 2仅文件 3文件+校验*/ +u_char version[2]; /* 版本 */ +#ifndef NO_ARP +u_int32_t rip = 0; /* 实际IP */ +u_char gateMAC[6]; /* 网关MAC */ +#endif + +extern char password[]; +extern char nic[]; +extern char dataFile[]; +extern u_int32_t ip, mask, gateway, dns, pingHost; +extern u_char localMAC[], destMAC[]; +extern unsigned startMode, dhcpMode; + +static int checkFile(); /* 检查数据文件 */ +static int getVersion(); /* 获取8021x.exe版本号 */ +static int getAddress(); /* 获取网络地址 */ +static u_char encode(u_char base); /* 锐捷算法,颠倒一个字节的8位 */ +static void checkSum(u_char *buf); /* 锐捷算法,计算两个字节的检验值 */ +static int setProperty(u_char type, const u_char *value, int length); /* 设置指定属性 */ +static int readPacket(int type); /* 读取数据 */ +static int Check(const u_char *md5Seed); /* 校验算法 */ + +char *formatIP(u_int32_t ip) +{ + static char tmp[16]; + u_char *p = (u_char *)(&ip); + sprintf(tmp, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + return tmp; +} + +char *formatHex(const void *buf, int length) +{ + static char hex[385]; + u_char *p = (u_char *)buf; + int i; + if (length > 128) + length = 128; + for (i=0; i0x397) + goto fileError; + return 0; + +fileError: + if (dataFile[strlen(dataFile)-1] != '/') + printf("!! 所选文件%s无效,改用内置数据认证。\n", dataFile); + return -1; +} + +static int getVersion() { + char file[0x100], *p; + DWORD ver; + strcpy(file, dataFile); + if ((p=strrchr(file, '/')+1) == (void *)1) + p = file; + strcpy(p, "8021x.exe"); + if ((ver=getVer(file)) == (DWORD)-1) + return -1; + p = (char *)&ver; + version[0] = p[2]; + version[1] = p[0]; + bufType = 1; + return 0; +} + +void newBuffer() +{ + if (dataFile[0] == '\0') + strcpy(dataFile, DATAFILE); + getVersion(); + if (checkFile() == 0) + bufType += 2; + else fillSize = (bufType==0 ? 0x80 : 0x1d7); + fillBuf = (u_char *)malloc(fillSize); +} + +static int getAddress() +{ + struct ifreq ifr; +#ifndef SIOCGIFHWADDR /* BSD、MacOS */ + struct ifaddrs *ifap, *p = NULL; + struct sockaddr_dl *sdl; +#endif + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + printf("!! 创建套接字失败!\n"); + return -1; + } + strcpy(ifr.ifr_name, nic); + +#ifdef SIOCGIFHWADDR + if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) + goto getMACError; + memcpy(localMAC, ifr.ifr_hwaddr.sa_data, 6); +#else + if (getifaddrs(&ifap) == 0) + { + for (p=ifap; p; p=p->ifa_next) + { + if (p->ifa_name && strcmp(p->ifa_name, nic)==0) + { + sdl = (struct sockaddr_dl *)p->ifa_addr; + memcpy(localMAC, sdl->sdl_data + sdl->sdl_nlen, 6); + break; + } + } + freeifaddrs(ifap); + } + if (p == NULL) + goto getMACError; +#endif + + if (startMode == 0) + memcpy(destMAC, STANDARD_ADDR, 6); + else if (startMode == 1) + memcpy(destMAC, RUIJIE_ADDR, 6); + +#ifndef NO_ARP + gateMAC[0] = 0xFE; + if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) + printf("!! 在网卡%s上获取IP失败!\n", nic); + else { + rip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + if (gateway!=0 && (startMode%3!=2 || ((u_char *)&gateway)[3]!=0x02)) + gateMAC[0] = 0xFF; + } + if (dhcpMode!=0 || ip==-1) + ip = rip; +#else + if (dhcpMode!=0 || ip==-1) { + if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) + printf("!! 在网卡%s上获取IP失败!\n", nic); + else + ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + } +#endif + + if (dhcpMode!=0 || mask==-1) { + if (ioctl(sock, SIOCGIFNETMASK, &ifr) < 0) + printf("!! 在网卡%s上获取子网掩码失败!\n", nic); + else + mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; + } + close(sock); + + printf("** 本机MAC:\t%s\n", formatHex(localMAC, 6)); + printf("** 使用IP:\t%s\n", formatIP(ip)); + printf("** 子网掩码:\t%s\n", formatIP(mask)); + return 0; + +getMACError: + close(sock); + printf("!! 在网卡%s上获取MAC失败!\n", nic); + return -1; +} + +static u_char encode(u_char base) /* 算法,将一个字节的8位颠倒并取反 */ +{ + u_char result = 0; + int i; + for (i=0; i<8; i++) + { + result <<= 1; + result |= base&0x01; + base >>= 1; + } + return ~result; +} + +static void checkSum(u_char *buf) /* 算法,计算两个字节的checksum */ +{ + u_char table[] = + { + 0x00,0x00,0x21,0x10,0x42,0x20,0x63,0x30,0x84,0x40,0xA5,0x50,0xC6,0x60,0xE7,0x70, + 0x08,0x81,0x29,0x91,0x4A,0xA1,0x6B,0xB1,0x8C,0xC1,0xAD,0xD1,0xCE,0xE1,0xEF,0xF1, + 0x31,0x12,0x10,0x02,0x73,0x32,0x52,0x22,0xB5,0x52,0x94,0x42,0xF7,0x72,0xD6,0x62, + 0x39,0x93,0x18,0x83,0x7B,0xB3,0x5A,0xA3,0xBD,0xD3,0x9C,0xC3,0xFF,0xF3,0xDE,0xE3, + 0x62,0x24,0x43,0x34,0x20,0x04,0x01,0x14,0xE6,0x64,0xC7,0x74,0xA4,0x44,0x85,0x54, + 0x6A,0xA5,0x4B,0xB5,0x28,0x85,0x09,0x95,0xEE,0xE5,0xCF,0xF5,0xAC,0xC5,0x8D,0xD5, + 0x53,0x36,0x72,0x26,0x11,0x16,0x30,0x06,0xD7,0x76,0xF6,0x66,0x95,0x56,0xB4,0x46, + 0x5B,0xB7,0x7A,0xA7,0x19,0x97,0x38,0x87,0xDF,0xF7,0xFE,0xE7,0x9D,0xD7,0xBC,0xC7, + 0xC4,0x48,0xE5,0x58,0x86,0x68,0xA7,0x78,0x40,0x08,0x61,0x18,0x02,0x28,0x23,0x38, + 0xCC,0xC9,0xED,0xD9,0x8E,0xE9,0xAF,0xF9,0x48,0x89,0x69,0x99,0x0A,0xA9,0x2B,0xB9, + 0xF5,0x5A,0xD4,0x4A,0xB7,0x7A,0x96,0x6A,0x71,0x1A,0x50,0x0A,0x33,0x3A,0x12,0x2A, + 0xFD,0xDB,0xDC,0xCB,0xBF,0xFB,0x9E,0xEB,0x79,0x9B,0x58,0x8B,0x3B,0xBB,0x1A,0xAB, + 0xA6,0x6C,0x87,0x7C,0xE4,0x4C,0xC5,0x5C,0x22,0x2C,0x03,0x3C,0x60,0x0C,0x41,0x1C, + 0xAE,0xED,0x8F,0xFD,0xEC,0xCD,0xCD,0xDD,0x2A,0xAD,0x0B,0xBD,0x68,0x8D,0x49,0x9D, + 0x97,0x7E,0xB6,0x6E,0xD5,0x5E,0xF4,0x4E,0x13,0x3E,0x32,0x2E,0x51,0x1E,0x70,0x0E, + 0x9F,0xFF,0xBE,0xEF,0xDD,0xDF,0xFC,0xCF,0x1B,0xBF,0x3A,0xAF,0x59,0x9F,0x78,0x8F, + 0x88,0x91,0xA9,0x81,0xCA,0xB1,0xEB,0xA1,0x0C,0xD1,0x2D,0xC1,0x4E,0xF1,0x6F,0xE1, + 0x80,0x10,0xA1,0x00,0xC2,0x30,0xE3,0x20,0x04,0x50,0x25,0x40,0x46,0x70,0x67,0x60, + 0xB9,0x83,0x98,0x93,0xFB,0xA3,0xDA,0xB3,0x3D,0xC3,0x1C,0xD3,0x7F,0xE3,0x5E,0xF3, + 0xB1,0x02,0x90,0x12,0xF3,0x22,0xD2,0x32,0x35,0x42,0x14,0x52,0x77,0x62,0x56,0x72, + 0xEA,0xB5,0xCB,0xA5,0xA8,0x95,0x89,0x85,0x6E,0xF5,0x4F,0xE5,0x2C,0xD5,0x0D,0xC5, + 0xE2,0x34,0xC3,0x24,0xA0,0x14,0x81,0x04,0x66,0x74,0x47,0x64,0x24,0x54,0x05,0x44, + 0xDB,0xA7,0xFA,0xB7,0x99,0x87,0xB8,0x97,0x5F,0xE7,0x7E,0xF7,0x1D,0xC7,0x3C,0xD7, + 0xD3,0x26,0xF2,0x36,0x91,0x06,0xB0,0x16,0x57,0x66,0x76,0x76,0x15,0x46,0x34,0x56, + 0x4C,0xD9,0x6D,0xC9,0x0E,0xF9,0x2F,0xE9,0xC8,0x99,0xE9,0x89,0x8A,0xB9,0xAB,0xA9, + 0x44,0x58,0x65,0x48,0x06,0x78,0x27,0x68,0xC0,0x18,0xE1,0x08,0x82,0x38,0xA3,0x28, + 0x7D,0xCB,0x5C,0xDB,0x3F,0xEB,0x1E,0xFB,0xF9,0x8B,0xD8,0x9B,0xBB,0xAB,0x9A,0xBB, + 0x75,0x4A,0x54,0x5A,0x37,0x6A,0x16,0x7A,0xF1,0x0A,0xD0,0x1A,0xB3,0x2A,0x92,0x3A, + 0x2E,0xFD,0x0F,0xED,0x6C,0xDD,0x4D,0xCD,0xAA,0xBD,0x8B,0xAD,0xE8,0x9D,0xC9,0x8D, + 0x26,0x7C,0x07,0x6C,0x64,0x5C,0x45,0x4C,0xA2,0x3C,0x83,0x2C,0xE0,0x1C,0xC1,0x0C, + 0x1F,0xEF,0x3E,0xFF,0x5D,0xCF,0x7C,0xDF,0x9B,0xAF,0xBA,0xBF,0xD9,0x8F,0xF8,0x9F, + 0x17,0x6E,0x36,0x7E,0x55,0x4E,0x74,0x5E,0x93,0x2E,0xB2,0x3E,0xD1,0x0E,0xF0,0x1E + }; + u_char *checkSum = buf + 0x15; + int i, index; + for (i=0; i<0x15; i++) + { + index = checkSum[0] ^ buf[i]; + checkSum[0] = checkSum[1] ^ table[index*2+1]; + checkSum[1] = table[index*2]; + } + for (i=0; i<0x17; i++) + buf[i] = encode(buf[i]); +} + +int fillHeader() +{ + if (getAddress() == -1) + return -1; + memset(fillBuf, 0, fillSize); + fillBuf[0x02] = 0x13; + fillBuf[0x03] = 0x11; + if (dhcpMode != 0) + fillBuf[0x04] = 0x01; /* DHCP位,使用1、不使用0 */ + memcpy(fillBuf+0x05, &ip, 4); + memcpy(fillBuf+0x09, &mask, 4); + memcpy(fillBuf+0x0D, &gateway, 4); + memcpy(fillBuf+0x11, &dns, 4); + checkSum(fillBuf); + return 0; +} + +static int setProperty(u_char type, const u_char *value, int length) +{ + u_char *p = fillBuf+0x46, *end = fillBuf+fillSize-length-8; /* 形如1a 28 00 00 13 11 17 22,至少8个字节 */ + while (p < end) + { + if (*p == 0x1a) /* 有些老版本没有前两个字节,包括xrgsu */ + p += 2; + if (p[4] == type) + { + memcpy(p+4+p[5]-length, value, length); + return 0; + } + p += p[5] + 4; + } + return -1; +} + +static int readPacket(int type) +{ + u_char dhcp[] = {0x00}; + FILE *fp = fopen(dataFile, "rb"); + if (fp == NULL) + goto fileError; + type %= 2; /* 偶数读Start包,奇数读Md5包 */ + fseek(fp, dataOffset+(fillSize-0x17)*type, SEEK_SET); + if (fread(fillBuf+0x17, fillSize-0x17, 1, fp) < 1) /* 前0x17字节是地址及校验值 */ + { + fclose(fp); + goto fileError; + } + fclose(fp); + if (dhcpMode == 1) /* 二次认证第一次 */ + dhcp[0] = 0x01; + setProperty(0x18, dhcp, 1); + setProperty(0x2D, localMAC, 6); + if (bufType == 3) + memcpy(fillBuf+0x3b, version, 2); + return 0; + +fileError: + printf("!! 所选文件%s无效,改用内置数据认证。\n", dataFile); + bufType -= 2; + if (bufType==1 && fillSize<0x1d7) { + free(fillBuf); + fillSize = 0x1d7; + fillBuf = (u_char *)malloc(fillSize); + } + return -1; +} + +void fillStartPacket() +{ + if (bufType <= 1) { /* 使用xrgsu? */ + const u_char packet0[] = { + 0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,0x2e,0x65,0x78,0x65,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0x11,0x00,0x28,0x1a, + 0x28,0x00,0x00,0x13,0x11,0x17,0x22,0x91,0x66,0x64,0x93,0x67,0x60,0x65,0x62,0x62, + 0x94,0x61,0x69,0x67,0x63,0x91,0x93,0x92,0x68,0x66,0x93,0x91,0x66,0x95,0x65,0xaa, + 0xdc,0x64,0x98,0x96,0x6a,0x9d,0x66,0x00,0x00,0x13,0x11,0x18,0x06,0x02,0x00,0x00 + }; + const u_char packet1[] = { + 0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,0x2e,0x65,0x78,0x65,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x0a,0x00,0x02,0x00,0x00,0x00,0x13,0x11,0x01,0x8c,0x1a, + 0x28,0x00,0x00,0x13,0x11,0x17,0x22,0x36,0x38,0x44,0x43,0x31,0x32,0x33,0x42,0x37, + 0x45,0x42,0x32,0x33,0x39,0x46,0x32,0x33,0x41,0x38,0x43,0x30,0x30,0x30,0x33,0x38, + 0x38,0x34,0x39,0x38,0x36,0x33,0x39,0x1a,0x0c,0x00,0x00,0x13,0x11,0x18,0x06,0x00, + 0x00,0x00,0x00,0x1a,0x0e,0x00,0x00,0x13,0x11,0x2d,0x08,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1a,0x08,0x00,0x00,0x13,0x11,0x2f,0x02,0x1a,0x09,0x00,0x00,0x13,0x11,0x35, + 0x03,0x01,0x1a,0x18,0x00,0x00,0x13,0x11,0x36,0x12,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x18,0x00,0x00,0x13,0x11, + 0x38,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x86, + 0x13,0x4c,0x1a,0x88,0x00,0x00,0x13,0x11,0x4d,0x82,0x36,0x38,0x64,0x63,0x31,0x32, + 0x33,0x62,0x30,0x37,0x65,0x62,0x32,0x33,0x39,0x66,0x32,0x33,0x61,0x38,0x30,0x64, + 0x63,0x66,0x32,0x35,0x38,0x37,0x35,0x64,0x30,0x35,0x37,0x37,0x30,0x63,0x37,0x32, + 0x31,0x65,0x34,0x35,0x36,0x34,0x35,0x65,0x35,0x33,0x37,0x61,0x62,0x33,0x35,0x31, + 0x62,0x62,0x36,0x33,0x31,0x35,0x35,0x61,0x65,0x31,0x36,0x32,0x36,0x31,0x36,0x37, + 0x65,0x62,0x30,0x39,0x32,0x32,0x33,0x65,0x32,0x61,0x30,0x61,0x37,0x38,0x30,0x33, + 0x31,0x31,0x36,0x31,0x61,0x63,0x30,0x39,0x64,0x61,0x32,0x64,0x63,0x30,0x37,0x33, + 0x36,0x39,0x33,0x61,0x34,0x66,0x35,0x61,0x32,0x39,0x32,0x38,0x36,0x37,0x35,0x31, + 0x66,0x39,0x37,0x66,0x34,0x64,0x30,0x34,0x36,0x38,0x1a,0x28,0x00,0x00,0x13,0x11, + 0x39,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1a,0x48,0x00,0x00,0x13,0x11,0x54,0x42,0x48,0x55,0x53,0x54,0x4d,0x4f, + 0x4f,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x08,0x00,0x00,0x13,0x11, + 0x55,0x02,0x1a,0x09,0x00,0x00,0x13,0x11,0x62,0x03,0x00,0x00,0x00,0x00,0x00,0x00 + }; + u_char dhcp[] = {0x00}; + if (dhcpMode == 1) /* 二次认证第一次 */ + dhcp[0] = 0x01; + if (bufType == 1) { + memcpy(fillBuf+0x17, packet1, sizeof(packet1)); + memcpy(fillBuf+0x3b, version, 2); + } else + memcpy(fillBuf+0x17, packet0, sizeof(packet0)); + setProperty(0x18, dhcp, 1); + setProperty(0x2D, localMAC, 6); + } + else if (readPacket(0) == -1) /* 读取数据失败就用默认的填充 */ + fillStartPacket(); +} + +void fillMd5Packet(const u_char *md5Seed) +{ + if (bufType <= 1) { /* 不使用数据包? */ + /* xrgsu的Md5包与Start包只有一个字节的差异,若以其他版本为基础,可进一步区别对待 */ + fillStartPacket(); + if (bufType == 1) + Check(md5Seed); + } else { + if (readPacket(1) == -1) + fillMd5Packet(md5Seed); + else + Check(md5Seed); + } + echoNo = 0x0000102B; /* 初始化echoNo */ +} + +static int Check(const u_char *md5Seed) /* 客户端校验 */ +{ + char final_str[129]; + int value; + printf("** 客户端版本:\t%d.%d\n", fillBuf[0x3B], fillBuf[0x3C]); + printf("** MD5种子:\t%s\n", formatHex(md5Seed, 16)); + value = check_init(dataFile); + if (value == -1) { + printf("!! 缺少8021x.exe信息,客户端校验无法继续!\n"); + return 1; + } + V2_check(md5Seed, final_str); + printf("** V2校验值:\t%s\n", final_str); + setProperty(0x17, (u_char *)final_str, 32); + check_free(); + return 0; +} + +void fillEchoPacket(u_char *echoBuf) +{ + int i; + u_int32_t dd1=htonl(echoKey + echoNo), dd2=htonl(echoNo); + u_char *bt1=(u_char *)&dd1, *bt2=(u_char *)&dd2; + echoNo++; + for (i=0; i<4; i++) + { + echoBuf[0x18+i] = encode(bt1[i]); + echoBuf[0x22+i] = encode(bt2[i]); + } +} + +void getEchoKey(const u_char *capBuf) +{ + int i, offset = 0x1c+capBuf[0x1b]+0x69+24; /* 通过比较了大量抓包,通用的提取点就是这样的 */ + u_char *base; + echoKey = ntohl(*(u_int32_t *)(capBuf+offset)); + base = (u_char *)(&echoKey); + for (i=0; i<4; i++) + base[i] = encode(base[i]); +} + +u_char *checkPass(u_char id, const u_char *md5Seed, int seedLen) +{ + u_char md5Src[80]; + int md5Len = strlen(password); + md5Src[0] = id; + memcpy(md5Src+1, password, md5Len); + md5Len++; + if (startMode % 3 == 2) /* 赛尔? */ + { + memcpy(md5Src+md5Len, "xxghlmxhzb", 10); + md5Len += 10; + } + memcpy(md5Src+md5Len, md5Seed, seedLen); + md5Len += seedLen; + return ComputeHash(md5Src, md5Len); +} + +void fillCernetAddr(u_char *buf) +{ + memcpy(buf+0x18, &ip, 4); + memcpy(buf+0x1C, &mask, 4); + memcpy(buf+0x20, &gateway, 4); + memset(buf+0x24, 0, 4); /* memcpy(buf+0x24, &dns, 4); */ +} + +int isOnline() +{ + u_char echoPacket[] = + { + 0x08,0x00,0x61,0xb2,0x02,0x00,0x01,0x00,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,0x20, + 0x74,0x6F,0x20,0x4D,0x65,0x6E,0x74,0x6F,0x48,0x55,0x53,0x54,0x21,0x0A,0x43,0x6F, + 0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x39, + 0x20,0x48,0x75,0x73,0x74,0x4D,0x6F,0x6F,0x6E,0x20,0x53,0x74,0x75,0x64,0x69,0x6F + }; + int sock=-1, rtVal, t; + struct pollfd pfd; + struct sockaddr_in dest; + if (pingHost == 0) + return 0; + memset(&dest, 0, sizeof(dest)); + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = pingHost; + if ((sock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + goto pingError; + pfd.fd = sock; + pfd.events = POLLIN; + for (t=1; t<=3; t++) { + if (sendto(sock, echoPacket, sizeof(echoPacket), 0, + (struct sockaddr *)&dest, sizeof(dest)) < 0) + goto pingError; + rtVal = poll(&pfd, 1, t*1000); + if (rtVal == -1) + goto pingError; + if (rtVal > 0) { + close(sock); + return 0; + } + } + close(sock); + return -1; + +pingError: + perror("!! Ping主机出错,关闭该功能"); + if (sock != -1) + close(sock); + pingHost = 0; + return 0; +} diff --git a/src/myfunc.h b/src/myfunc.h new file mode 100644 index 0000000..9b7d68c --- /dev/null +++ b/src/myfunc.h @@ -0,0 +1,26 @@ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:myfunc.h +* 摘 要:认证相关算法及方法 +* 作 者:HustMoon@BYHH +*/ +#ifndef HUSTMOON_MYFUNC_H +#define HUSTMOON_MYFUNC_H + +#include + +char *formatIP(u_int32_t ip); /* 格式化IP */ +char *formatHex(const void *buf, int length); /* 格式化成十六进制形式 */ +void newBuffer(); /* 检测数据文件有效性并分配内存 */ +int fillHeader(); /* 填充网络地址及校验值部分 */ +void fillStartPacket(); /* 填充Start包 */ +void fillMd5Packet(const u_char *md5Seed); /* 填充Md5包 */ +void fillEchoPacket(u_char *buf); /* 填充Echo包 */ +void getEchoKey(const u_char *capBuf); /* 获取EchoKey */ +u_char *checkPass(u_char id, const u_char *md5Seed, int seedLen); /* 计算密码的md5 */ +void fillCernetAddr(u_char *buf); /* 填充赛尔网络地址 */ +int isOnline(); /* ping主机判断是否掉线 */ + +#endif + diff --git a/src/myini.c b/src/myini.c new file mode 100644 index 0000000..c4103ef --- /dev/null +++ b/src/myini.c @@ -0,0 +1,203 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:myini.c +* 摘 要:读取ini文件+写入ini文件 +* 作 者:HustMoon@BYHH +* 修 改:2009.10.8 +*/ +#include "myini.h" +#include +#include + +#define NOT_COMMENT(c) (c!=';' && c!='#') /* 不是注释行 */ + +#ifndef strnicmp +#define strnicmp strncasecmp +#endif + +static void getLine(const char *buf, int inStart, int *lineStart, int *lineEnd); +static int findKey(const char *buf, const char *section, const char *key, + int *sectionStart, int *valueStart, unsigned long *valueSize); +static int getSection(const char *buf, int inStart); + +char *loadFile(const char *fileName) +{ + FILE *fp = NULL; + long size = 0; + char *buf = NULL; + if ((fp=fopen(fileName, "rb")) == NULL) + return NULL; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + rewind(fp); + buf = (char *)malloc(size+1); + buf[size] = '\0'; + if (fread(buf, size, 1, fp) < 1) + { + free(buf); + buf = NULL; + } + fclose(fp); + return buf; +} + +static void getLine(const char *buf, int inStart, int *lineStart, int *lineEnd) +{ + int start, end; + for (start=inStart; buf[start]==' ' || buf[start]=='\t' || buf[start]=='\r' || buf[start]=='\n'; start++); + for (end=start; buf[end]!='\r' && buf[end]!='\n' && buf[end]!='\0'; end++); + *lineStart = start; + *lineEnd = end; +} + +static int findKey(const char *buf, const char *section, const char *key, + int *sectionStart, int *valueStart, unsigned long *valueSize) +{ + int lineStart, lineEnd, i; + for (*sectionStart=-1, lineEnd=0; buf[lineEnd]!='\0'; ) + { + getLine(buf, lineEnd, &lineStart, &lineEnd); + if (buf[lineStart] == '[') + { + for (i=++lineStart; i /* for free() */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +char *loadFile(const char *fileName); /* 读取文件 */ +int getString(const char *buf, const char *section, const char *key, + const char *defaultValue, char *value, unsigned long size); /* 读取字符串 */ +int getInt(const char *buf, const char *section, const char *key, int defaultValue); /* 读取整数 */ +void setString(char **buf, const char *section, const char *key, const char *value); /* 设置字符串,value=NULL则删除key,key=NULL则删除section */ +void setInt(char **buf, const char *section, const char *key, int value); /* 设置整数 */ +int saveFile(const char *buf, const char *fileName); /* 写入文件 */ + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/mystate.c b/src/mystate.c new file mode 100644 index 0000000..2daf147 --- /dev/null +++ b/src/mystate.c @@ -0,0 +1,331 @@ +/* -*- Mode: C; tab-width: 4; -*- */ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:mystate.c +* 摘 要:改变认证状态 +* 作 者:HustMoon@BYHH +* 邮 箱:www.ehust@gmail.com +*/ +#include "mystate.h" +#include "myfunc.h" +#include "dlfunc.h" +#include +#include +#include + +#define MAX_SEND_COUNT 3 /* 最大超时次数 */ + +volatile int state = ID_DISCONNECT; /* 认证状态 */ +const u_char *capBuf = NULL; /* 抓到的包 */ +static u_char sendPacket[0x3E8]; /* 用来发送的包 */ +static int sendCount = 0; /* 同一阶段发包计数 */ + +extern const u_char STANDARD_ADDR[]; +extern char userName[]; +extern unsigned startMode; +extern unsigned dhcpMode; +extern u_char localMAC[], destMAC[]; +extern unsigned timeout; +extern unsigned echoInterval; +extern unsigned restartWait; +extern char dhcpScript[]; +extern pcap_t *hPcap; +extern u_char *fillBuf; +extern unsigned fillSize; +extern u_int32_t pingHost; +#ifndef NO_ARP +extern u_int32_t rip, gateway; +extern u_char gateMAC[]; +static void sendArpPacket(); /* ARP监视 */ +#endif + +static void setTimer(unsigned interval); /* 设置定时器 */ +static int renewIP(); /* 更新IP */ +static void fillEtherAddr(u_int32_t protocol); /* 填充MAC地址和协议 */ +static int sendStartPacket(); /* 发送Start包 */ +static int sendIdentityPacket(); /* 发送Identity包 */ +static int sendChallengePacket(); /* 发送Md5 Challenge包 */ +static int sendEchoPacket(); /* 发送心跳包 */ +static int sendLogoffPacket(); /* 发送退出包 */ +static int waitEchoPacket(); /* 等候响应包 */ + +static void setTimer(unsigned interval) /* 设置定时器 */ +{ + struct itimerval timer; + timer.it_value.tv_sec = interval; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = interval; + timer.it_interval.tv_usec = 0; + setitimer(ITIMER_REAL, &timer, NULL); +} + +int switchState(int type) +{ + if (state == type) /* 跟上次是同一状态? */ + sendCount++; + else + { + state = type; + sendCount = 0; + } + if (sendCount>=MAX_SEND_COUNT && type!=ID_ECHO) /* 超时太多次? */ + { + switch (type) + { + case ID_START: + printf(">> 找不到服务器,重启认证!\n"); + break; + case ID_IDENTITY: + printf(">> 发送用户名超时,重启认证!\n"); + break; + case ID_CHALLENGE: + printf(">> 发送密码超时,重启认证!\n"); + break; + case ID_WAITECHO: + printf(">> 等候响应包超时,自行响应!\n"); + return switchState(ID_ECHO); + } + return restart(); + } + switch (type) + { + case ID_DHCP: + return renewIP(); + case ID_START: + return sendStartPacket(); + case ID_IDENTITY: + return sendIdentityPacket(); + case ID_CHALLENGE: + return sendChallengePacket(); + case ID_WAITECHO: /* 塞尔的就不ping了,不好计时 */ + return waitEchoPacket(); + case ID_ECHO: + if (pingHost && sendCount*echoInterval > 60) { /* 1分钟左右 */ + if (isOnline() == -1) { + printf(">> 认证掉线,开始重连!\n"); + return switchState(ID_START); + } + sendCount = 1; + } +#ifndef NO_ARP + if (gateMAC[0] != 0xFE) + sendArpPacket(); +#endif + return sendEchoPacket(); + case ID_DISCONNECT: + return sendLogoffPacket(); + } + return 0; +} + +int restart() +{ + if (startMode >= 3) /* 标记服务器地址为未获取 */ + startMode -= 3; + state = ID_START; + sendCount = -1; + setTimer(restartWait); /* restartWait秒后或者服务器请求后重启认证 */ + return 0; +} + +static int renewIP() +{ + setTimer(0); /* 取消定时器 */ + printf(">> 正在获取IP...\n"); + system(dhcpScript); + printf(">> 操作结束。\n"); + dhcpMode += 3; /* 标记为已获取,123变为456,5不需再认证*/ + if (fillHeader() == -1) + exit(EXIT_FAILURE); + if (dhcpMode == 5) + return switchState(ID_ECHO); + return switchState(ID_START); +} + +static void fillEtherAddr(u_int32_t protocol) +{ + memset(sendPacket, 0, 0x3E8); + memcpy(sendPacket, destMAC, 6); + memcpy(sendPacket+0x06, localMAC, 6); + *(u_int32_t *)(sendPacket+0x0C) = htonl(protocol); +} + +static int sendStartPacket() +{ + if (startMode%3 == 2) /* 赛尔 */ + { + if (sendCount == 0) + { + printf(">> 寻找服务器...\n"); + memcpy(sendPacket, STANDARD_ADDR, 6); + memcpy(sendPacket+0x06, localMAC, 6); + *(u_int32_t *)(sendPacket+0x0C) = htonl(0x888E0101); + *(u_int16_t *)(sendPacket+0x10) = 0; + memset(sendPacket+0x12, 0xa5, 42); + setTimer(timeout); + } + return pcap_sendpacket(hPcap, sendPacket, 60); + } + if (sendCount == 0) + { + printf(">> 寻找服务器...\n"); + fillStartPacket(); + fillEtherAddr(0x888E0101); + memcpy(sendPacket+0x12, fillBuf, fillSize); + setTimer(timeout); + } + return pcap_sendpacket(hPcap, sendPacket, 0x3E8); +} + +static int sendIdentityPacket() +{ + int nameLen = strlen(userName); + if (startMode%3 == 2) /* 赛尔 */ + { + if (sendCount == 0) + { + printf(">> 发送用户名...\n"); + *(u_int16_t *)(sendPacket+0x0E) = htons(0x0100); + *(u_int16_t *)(sendPacket+0x10) = *(u_int16_t *)(sendPacket+0x14) = htons(nameLen+30); + sendPacket[0x12] = 0x02; + sendPacket[0x16] = 0x01; + sendPacket[0x17] = 0x01; + fillCernetAddr(sendPacket); + memcpy(sendPacket+0x28, "03.02.05", 8); + memcpy(sendPacket+0x30, userName, nameLen); + setTimer(timeout); + } + sendPacket[0x13] = capBuf[0x13]; + return pcap_sendpacket(hPcap, sendPacket, nameLen+48); + } + if (sendCount == 0) + { + printf(">> 发送用户名...\n"); + fillEtherAddr(0x888E0100); + nameLen = strlen(userName); + *(u_int16_t *)(sendPacket+0x14) = *(u_int16_t *)(sendPacket+0x10) = htons(nameLen+5); + sendPacket[0x12] = 0x02; + sendPacket[0x13] = capBuf[0x13]; + sendPacket[0x16] = 0x01; + memcpy(sendPacket+0x17, userName, nameLen); + memcpy(sendPacket+0x17+nameLen, fillBuf, fillSize); + setTimer(timeout); + } + return pcap_sendpacket(hPcap, sendPacket, 0x3E8); +} + +static int sendChallengePacket() +{ + int nameLen = strlen(userName); + if (startMode%3 == 2) /* 赛尔 */ + { + if (sendCount == 0) + { + printf(">> 发送密码...\n"); + *(u_int16_t *)(sendPacket+0x0E) = htons(0x0100); + *(u_int16_t *)(sendPacket+0x10) = *(u_int16_t *)(sendPacket+0x14) = htons(nameLen+22); + sendPacket[0x12] = 0x02; + sendPacket[0x13] = capBuf[0x13]; + sendPacket[0x16] = 0x04; + sendPacket[0x17] = 16; + memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16); + memcpy(sendPacket+0x28, userName, nameLen); + setTimer(timeout); + } + return pcap_sendpacket(hPcap, sendPacket, nameLen+40); + } + if (sendCount == 0) + { + printf(">> 发送密码...\n"); + fillMd5Packet(capBuf+0x18); + fillEtherAddr(0x888E0100); + *(u_int16_t *)(sendPacket+0x14) = *(u_int16_t *)(sendPacket+0x10) = htons(nameLen+22); + sendPacket[0x12] = 0x02; + sendPacket[0x13] = capBuf[0x13]; + sendPacket[0x16] = 0x04; + sendPacket[0x17] = 16; + memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16); + memcpy(sendPacket+0x28, userName, nameLen); + memcpy(sendPacket+0x28+nameLen, fillBuf, fillSize); + setTimer(timeout); + } + return pcap_sendpacket(hPcap, sendPacket, 0x3E8); +} + +static int sendEchoPacket() +{ + if (startMode%3 == 2) /* 赛尔 */ + { + *(u_int16_t *)(sendPacket+0x0E) = htons(0x0106); + *(u_int16_t *)(sendPacket+0x10) = 0; + memset(sendPacket+0x12, 0xa5, 42); + switchState(ID_WAITECHO); /* 继续等待 */ + return pcap_sendpacket(hPcap, sendPacket, 60); + } + if (sendCount == 0) + { + u_char echo[] = + { + 0x00,0x1E,0xFF,0xFF,0x37,0x77,0x7F,0x9F,0xFF,0xFF,0xD9,0x13,0xFF,0xFF,0x37,0x77, + 0x7F,0x9F,0xFF,0xFF,0xF7,0x2B,0xFF,0xFF,0x37,0x77,0x7F,0x3F,0xFF + }; + printf(">> 发送心跳包以保持在线...\n"); + fillEtherAddr(0x888E01BF); + memcpy(sendPacket+0x10, echo, sizeof(echo)); + setTimer(echoInterval); + } + fillEchoPacket(sendPacket); + return pcap_sendpacket(hPcap, sendPacket, 0x2D); +} + +static int sendLogoffPacket() +{ + setTimer(0); /* 取消定时器 */ + if (startMode%3 == 2) /* 赛尔 */ + { + *(u_int16_t *)(sendPacket+0x0E) = htons(0x0102); + *(u_int16_t *)(sendPacket+0x10) = 0; + memset(sendPacket+0x12, 0xa5, 42); + return pcap_sendpacket(hPcap, sendPacket, 60); + } + fillStartPacket(); /* 锐捷的退出包与Start包类似,不过其实不这样也是没问题的 */ + fillEtherAddr(0x888E0102); + memcpy(sendPacket+0x12, fillBuf, fillSize); + return pcap_sendpacket(hPcap, sendPacket, 0x3E8); +} + +static int waitEchoPacket() +{ + if (sendCount == 0) + setTimer(echoInterval); + return 0; +} + +#ifndef NO_ARP +static void sendArpPacket() +{ + u_char arpPacket[0x3C] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x06,0x00,0x01, + 0x08,0x00,0x06,0x04,0x00}; + + if (gateMAC[0] != 0xFF) { + memcpy(arpPacket, gateMAC, 6); + memcpy(arpPacket+0x06, localMAC, 6); + arpPacket[0x15]=0x02; + memcpy(arpPacket+0x16, localMAC, 6); + memcpy(arpPacket+0x1c, &rip, 4); + memcpy(arpPacket+0x20, gateMAC, 6); + memcpy(arpPacket+0x26, &gateway, 4); + pcap_sendpacket(hPcap, arpPacket, 0x3C); + } + memset(arpPacket, 0xFF, 6); + memcpy(arpPacket+0x06, localMAC, 6); + arpPacket[0x15]=0x01; + memcpy(arpPacket+0x16, localMAC, 6); + memcpy(arpPacket+0x1c, &rip, 4); + memset(arpPacket+0x20, 0, 6); + memcpy(arpPacket+0x26, &gateway, 4); + pcap_sendpacket(hPcap, arpPacket, 0x2A); +} +#endif diff --git a/src/mystate.h b/src/mystate.h new file mode 100644 index 0000000..258d9b7 --- /dev/null +++ b/src/mystate.h @@ -0,0 +1,22 @@ +/* +* Copyright (C) 2009, HustMoon Studio +* +* 文件名称:mystate.h +* 摘 要:改变认证状态 +* 作 者:HustMoon@BYHH +*/ +#ifndef HUSTMOON_MYSTATE_H +#define HUSTMOON_MYSTATE_H + +#define ID_DISCONNECT 0 /* 断开状态 */ +#define ID_START 1 /* 寻找服务器 */ +#define ID_IDENTITY 2 /* 发送用户名 */ +#define ID_CHALLENGE 3 /* 发送密码 */ +#define ID_ECHO 4 /* 发送心跳包 */ +#define ID_DHCP 5 /* 更新IP */ +#define ID_WAITECHO 6 /* 等待心跳包 */ + +int switchState(int type); /* 改变状态 */ +int restart(); /* 重启认证 */ + +#endif diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..b3dfdcd --- /dev/null +++ b/src/types.h @@ -0,0 +1,10 @@ +#ifndef TYPES_H +#define TYPES_H +typedef unsigned char *POINTER; +typedef unsigned char BYTE; +typedef unsigned char UCHAR; +typedef unsigned short int WORD; +typedef int LONG; +typedef unsigned int DWORD; +typedef unsigned int UINT4; +#endif