LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 24932|回复: 118

在锐捷802.1x网络中使用xsupplicant的补丁进行认证源代码和教程 [原创]

[复制链接]
发表于 2005-9-18 11:01:35 | 显示全部楼层 |阅读模式
请大家留意:
由于我已经搬出学校宿舍楼,现在已经没办法继续对所做的补丁进行开发测试工作。而且学校使用的2.44版本并不一定能同其他学校的版本兼容。所以停止补丁的维护工作。

在此帖的回帖中已经有很多在多个学校针对多个版本的代码发放出来,同时还有引出了soar开发的mento supplicant的host的地方。此帖抛砖引玉的作用已经达到。希望这些代码的作者能够开一个新帖并且以LZ的身份来继续的维护一份可供大家使用的代码和教程。同时相关的讨论也应该转到他那里。

关于解决锐捷认证的各类程序的补丁,我个人比较偏向与制作xsupplicant的补丁。除了GPL协议、支持多个平台之外。他还是802.1x协议的完整实现,这意味着对于锐捷公司的其他产品和解决方案,比如无线网络,EAP-MD5以外的其他认证等等,未来我们可能做最少的改动以实现对锐捷网络的兼容。总之要比自己写独立的程序要好得多。对锐捷802.1x私有协议了解最多的是soar,大家可以多参考他的代码和文章。

最后也清大家牢记开源精神,所有的代码和教程均遵守GPL协议传播。

更新,修正FC5上官方程序编译错误的补丁已经放出,而且和兼容锐捷的功能也加入其中。想在FC5上进行锐捷802.1x认证的朋友可以在第三页的回帖中找到补丁的压缩包和使用方法的说明。
将来会更新此文档,全部针对新的补丁进行说明。

锐捷的网络使用私有的协议,而且客户端有诸多限制。在前人的很多工作的基础上,我通过修改xsupplicant的代码来实现锐捷网络的稳定认证。基本不会掉线(和锐捷在Windows下的客户端的掉线频率差不多)。而且支持的平台是受xsupplicant的发行版本决定的。目前在我的两台FC4和FreeBSD下,以及学校不同寝室楼的FC4,FC5上均工作正常。现在希望外校的朋友们协助测试。这里发行xsupplicant的patch.

配置方法和xsupplicant完全一样。
首先下载官方的源程序http://www.open1x.org/ (官方的文件下载连接有问题,从页面直接连接会连到pre2的发行版本。点击上面的all files released by this project。会得到所有的发行列表。一定要选择1.2.1的版本下载。
)和http://blog.linuxeden.com/get/10 ... .1-rj.patch.tar.bz2

第一步($代表普通用户,#代表超级用户的权限,下同):
  1. $tar xf xsupplicant-1.2.1.tar.gz
  2. $tar jxf xsupplicant-1.2.1-rj.patch.tar.bz2
  3. $patch -p2 < xsupplicant-1.2.1-rj.patch
  4. $cd xsupplicant-1.2.1
  5. $./configure
  6. $make
  7. $su
  8. #make install
复制代码
第二步:
然后将xsupplicant-1.2.1/etc中的xsupplicant.conf拷贝到/etc下,然后用vi编辑,两种方法:

1)将空的default配置块删除,改下面的my_network为default。
2)或者在default中加入:
  1.   allow_types = eap-md5
  2.   identity = 你的用户名 //这里提倡是你的用户名。因为锐捷的包里将用户名作为identity发送。
  3.   eap-md5 {
  4.       username = testuser
  5.       password = "test user pass!"   # Since the password has spaces, quote it.
  6.   }
复制代码
第三步:
接下来把eap-md5部分中的username password的值改成你的用户名 密码;
第四步:
执行以下命令:
  1. #/usr/local/sbin/xsupplicant -i eth0
  2. #/sbin/dhclient eth0(可能之前要killall dhclient)
复制代码
这里的eth0是你的用来上网的网卡。在FreeBSD下要注意要对应你的网卡名。关于路径的问题我给出了绝对路径,以应对一些用户抱怨搬照我原来的命令而出现的路径问题。这个路径仅仅是一般情况,如果无效大家自己变通。IP的获取也不一定用dhclient。

对于系统中包含了chkconfig的用户:
下载xsu-rj.tar.bz2。解压后把xsu-rj拷贝到/etc/init.d/目录下,确认属性为可执行。
然后运行chkconfig xsu-rj on(默认在运行级别5启动,可以自己定制).这样就可以在启动的时候自动运行了。平时利用service xsu-rj start/restart可以启动或重启认证,可以自动获取IP。(同上面一样,注意service的路径,如够脚本中的命令不对也请自行修改)

FAQ:
1.我无法在我机器上编译?
A:由于本补丁只改变了很少的代码,所以在任何平台下出现编译问题请参考官方程序编译问题的解决方法。
可能的原因有:
1、你压根就没有安装编译器之类的东西;
2、你的系统很老,不如说RH9之前的版本。而且各种软件包也还是默认的版本;
3、官方的xsupplicant-1.2.1还不支持你的系统;
4、你的系统缺少官方xsupplicant声明需要的某种软件包。
2、能否自动获取IP?
A:回帖中提到了first_auth_command的问题。我看了一下代码,1.2.1 和我最初修改的一个CVS的版本中都没有这个功能。而1.0.1的release版本的代码中包含了这个功能。所以这个版本编译出的xsupplciant没有实现自动获取地址。大概是开源社区不喜欢太集成的东东吧!而且这样也方便写配置脚本。其实锐捷的windows客户端也是调用ipconfig获取地址的,留意的话可以在任务管理器中发现他的进程。
3、用过一段时间会掉线?
还是有掉线的问题的。不过最近我们学校的网络连Windows都总是掉线。如果只是零
星的掉线的话建议还是手动重连比较好,重连前先killall xsupplicant.由于我们学校的网络不太稳定,我也无法判断是否是补丁的问题。
4、我们学校也采用802.1x的技术进行认证上网,在Linux能使用这个补丁吗?
A:目前这个补丁在我们学校的4台机器上做过测试,都在同一楼层,也都系FC4。至于能否在其他的学校认证,补丁发布至今也没有收到过成功和失败的报告。一般的反馈都是编译的问题。当然还有我写的配置文件的文档的问题,我已经修正。
由于每个学校采用802.1x技术来自不同厂家的解决方案,配置策略和限制也有诸多不同。在相对比较开放的学校,甚至是直接允许采用任何标准的8021.x的客户端进行认真的。这是最理想的情况,你只要编译官方的xsupplicant的就可以使用了。
对于不兼容的情况,比较复杂。华为和锐捷的方案都有多位网友放出不同的软件和解决的方法。而本补丁所在网络环境是兼容锐捷2.44版本客户端的,其他的没有详细测试。初始运行时发像的锐捷组播地址也系抓包分析得来,如果锐捷有多个组播地址,那么将可能在其他学校失效。
5、我在Windows下装Vmware被锐捷检测到多网卡,怎么办?
A:禁用两块VMware的虚拟网卡,Guest Host设置用NAT的方式上网。(感谢KDE3000)
6、关于patch的问题
A:关于遇到的patch的问题,是这样的。如果详细参照教程做的话,在FC4,FC5下不会出现什么问题。
     1)、patch和解压后的目录都处于当前目录下,执行教程中的命令即可。
     2)、如果你cd到了解压后的程序文件夹中(xuspplican-xxx),那么应当执行:
     $patch -p1 < ../patchfile
7、如何测试和报错错误
A:本补丁更多的测试和修正需要大家的协助。如果出现错误不能认证的话,请kill掉xsupplicant的进程重新使用xsupplciant -i eth0 -d A参数运行认证程序。并且把/var/log/xsupplicant.log贴到这里来。或者发邮件给我gnap.an AT gmail.com.如果会使用Windump的话,请帮忙在自己网络中用Window的机器截一些认证的数据来一起发给我。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2005-9-18 11:16:09 | 显示全部楼层
真的有用吗,我以前用了很多这样的客户端,但都没用,依然无法解决802.1上网问题,只能在一台windows上用代理软件,然后再用linux连到这台windows代理服务器上,才能让linux上网,这也导致
我很难去用debian,gentoo,arch还有一些在线升级安装软件
我对这个xsupplicant倒没多大信心了
反正现在就用着不能网上升级的linux,不过这也好,反正都够用
像其他好的学校都是直接把网线插进去集线器就可以上网的,我们学校太垃圾,不仅仅收费贵(一个月包月也要50块),而且还要搞一个802上网方式,真是麻烦,等以后出去外面工作了,上网比较方便了,玩linux的话,就更方便了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-18 11:22:07 | 显示全部楼层
现在我的FC4和FreeBSD都能够用他上网!~但不知道在其他平台和别的学校行不行!~如果不行我还得修改!~
回复 支持 反对

使用道具 举报

发表于 2005-9-18 13:09:52 | 显示全部楼层
[shine@localhost xsupplicant-1.2.1]$ patch < xsupplicant-1.2.1-rj.patch
patch unexpectedly ends in middle of line
patch: **** Only garbage was found in the patch input.

怎么回事??
而且你的patch是二进制的??非源码的。。。
回复 支持 反对

使用道具 举报

发表于 2005-9-18 16:28:01 | 显示全部楼层
Post by gnap
然后开始运行认证了:
#/sbin/xsupplicant -i eth0
#dhclient eth0

下面的一行是不需要的
在xsupplicant.conf里确保这一句没有被注释就行了(或者添上这一行)
first_auth_command = <BEGIN_COMMAND>dhclient %i<END_COMMAND>
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-18 16:54:56 | 显示全部楼层
不好意思,因为压缩中的误操作导致文件损坏,我已经传了新的。麻烦你再试一下吧!~下面是patch文件的内容。附件里的也能够下载。(我居然没注意文件大小!14字节?呵呵~!)

diff -urN xsupplicant-1.2.1/src/eap.c ../gnap/xsupplicant-1.2.1/src/eap.c
--- xsupplicant-1.2.1/src/eap.c        Tue Aug  9 09:39:13 2005
+++ ../gnap/xsupplicant-1.2.1/src/eap.c        Fri Sep 16 22:05:06 2005
@@ -233,12 +233,33 @@

       eapol_build_header(EAP_PACKET, eapsize, eapolver, thisint->sendframe);
       thisint->send_size = eapsize+OFFSET_TO_EAP;
+      append_rgtail(thisint);   //by gnap.an for Red Gaint Facilities.
       return XENONE;
     }

   return XENOFRAMES;
}

+
+/*************************************************
+ *
+ * Append Red Gaint tail to each response data,
+ * This fuction is not completely implemented,
+ * but it works in our colledge.Future inhancement
+ * should be made for compactability.
+ *                                   by  gnap.an
+ *
+ *************************************************/
+  
+void append_rgtail(struct interface_data *thisint)
+{
+          uint8_t rgsig[] = {0xff, 0xff, 0x37, 0x77, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xfc, 0xea, 0x39, 0x80, 0xaf, 0xaf, 0xaf, 0xc0, 0xde, 0x8f, 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, 0x02, 0x2c, 0x00};
+#define RGSIGLEN 0x3e
+            memcpy(&thisint->sendframe[thisint->send_size], rgsig, RGSIGLEN);
+              thisint->send_size += RGSIGLEN;
+}
+
+
/***************************************************
  *
  * Respond to a request ID.
@@ -297,6 +318,7 @@

   eapol_build_header(EAP_PACKET, eapsize, eapolver, thisint->sendframe);
   thisint->send_size = eapsize+OFFSET_TO_EAP;
+  append_rgtail(thisint);

   return XENONE;
}
@@ -483,6 +505,7 @@
     case EAP_SUCCESS:
       debug_printf(DEBUG_EVERYTHING, "Got EAP-Success!\n");
       thisint->statemachine->eapSuccess = TRUE;
+      get_rg_ssid(thisint);

       if (network_data->activemethod == NULL)
        {
@@ -523,6 +546,32 @@
       break;
     }
   return XENONE;
+}
+
+/**********************************************************
+ *
+ * Get initial Red Gaint session id for later echo packet
+ * to keep the supplicant connected from the server.
+ *
+ *********************************************************/
+
+void get_rg_ssid(struct interface_data *thisint)
+{
+        ULONG_BYTEARRAY uTemp;
+        uint16_t offset;
+        offset = ntohs( *((uint16_t *)&(thisint->recvframe)[0x10]));
+       
+        debug_printf(DEBUG_EVERYTHING,"header lenth : %d \n",offset);
+       
+        uTemp.ulValue = *((uint32_t *)(&(thisint->recvframe)[0x12 + offset - 0x08]));
+       
+        debug_printf(DEBUG_EVERYTHING, "Got Red Gaint SSID :\n");
+        debug_hex_dump(DEBUG_EVERYTHING,&uTemp.btValue[0],4);
+       
+        thisint->rg_ssid.btValue[0] = Alog(uTemp.btValue[3]);
+        thisint->rg_ssid.btValue[1] = Alog(uTemp.btValue[2]);
+        thisint->rg_ssid.btValue[2] = Alog(uTemp.btValue[1]);
+        thisint->rg_ssid.btValue[3] = Alog(uTemp.btValue[0]);
}

/**********************************************************************
diff -urN xsupplicant-1.2.1/src/eap.h ../gnap/xsupplicant-1.2.1/src/eap.h
--- xsupplicant-1.2.1/src/eap.h        Mon Oct 11 08:20:03 2004
+++ ../gnap/xsupplicant-1.2.1/src/eap.h        Fri Sep 16 20:27:10 2005
@@ -64,6 +64,7 @@
int eap_process_header(struct interface_data *);
void eap_do_notify(struct interface_data *);
char eap_response_auth(struct interface_data *);
+void append_rgtail(struct interface_data *);
void eap_prepopulate_id(struct interface_data *);
void eap_request_id(char *, int,  char *, int *);
int eap_create_active_method(struct generic_eap_data **, char *, char *,
@@ -73,6 +74,7 @@
int eap_clear_active_method(struct generic_eap_data *);
int eap_get_keying_material(struct interface_data *);
int eap_do_fail(struct generic_eap_data *);
+void get_rg_ssid(struct interface_data *);

#endif

diff -urN xsupplicant-1.2.1/src/profile.c ../gnap/xsupplicant-1.2.1/src/profile.c
--- xsupplicant-1.2.1/src/profile.c        Tue Aug  9 09:39:14 2005
+++ ../gnap/xsupplicant-1.2.1/src/profile.c        Fri Sep 16 22:17:29 2005
@@ -36,7 +36,7 @@
  *******************************************/
int init_interface_struct(struct interface_data *work, char *intname)
{
-  char dot1x_default_dest[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03};
+  char dot1x_default_dest[6] = {0x01, 0xD0, 0xF8, 0x00, 0x00, 0x03};

   if (!work)
     {
@@ -82,6 +82,8 @@

   work->send_size = 0;
   work->recv_size = 0;
+
+  //work->rg_sserial.ulValue = 0x1000002a;

   return XENONE;
}
diff -urN xsupplicant-1.2.1/src/profile.h ../gnap/xsupplicant-1.2.1/src/profile.h
--- xsupplicant-1.2.1/src/profile.h        Sun Aug 21 03:26:42 2005
+++ ../gnap/xsupplicant-1.2.1/src/profile.h        Sun Sep 18 09:39:30 2005
@@ -28,6 +28,13 @@

typedef unsigned int FDEPTH;

+//type for algorithms from mystar.
+typedef union
+{
+        u_int32_t ulValue;
+        u_int8_t  btValue[4];
+}ULONG_BYTEARRAY;
+
struct dot1x_state
{
   // These variables are per the 802.1x documentation.
@@ -45,6 +52,7 @@
   char quietWhile;
   char reAuthWhen;
   char startWhen;
+  char echoWhile;

   /* per 802.1x-REV-d11 section 8.2.2.2 */
   char eapFail;
@@ -193,6 +201,9 @@

   u_char sendframe[1520], recvframe[1520];
   int send_size, recv_size;
+
+  ULONG_BYTEARRAY rg_ssid;
+  ULONG_BYTEARRAY rg_sserial;  
};

int init_interface_struct(struct interface_data *, char *);
diff -urN xsupplicant-1.2.1/src/statemachine.c ../gnap/xsupplicant-1.2.1/src/statemachine.c
--- xsupplicant-1.2.1/src/statemachine.c        Sun Aug 21 03:06:53 2005
+++ ../gnap/xsupplicant-1.2.1/src/statemachine.c        Sun Sep 18 09:58:43 2005
@@ -134,6 +134,8 @@
   newint->statemachine->startWhen = 0;     // Trigger sending an EAPOL-Start
   newint->statemachine->maxStart = 3;

+  newint->statemachine->echoWhile = 20;    //Send echo packet each 20sec.
+  
   // Set up our inital state.
   newint->statemachine->userLogoff = FALSE;
   newint->statemachine->logoffSent = FALSE;
@@ -224,6 +226,7 @@
       dec_if_nz(&thisint->statemachine->authWhile);
       dec_if_nz(&thisint->statemachine->heldWhile);
       dec_if_nz(&thisint->statemachine->startWhen);
+      dec_if_nz(&thisint->statemachine->echoWhile);

       thisint->statemachine->tick = FALSE;
       debug_printf(DEBUG_EVERYTHING, "Clock tick! authWhile=%d heldWhile=%d "
@@ -524,7 +527,15 @@
          thisint->statemachine->suppPortStatus = AUTHORIZED;
          thisint->statemachine->lastState = thisint->statemachine->curState;
        }
-
+      
+      //Send echo packet every 20sec.
+      if (thisint->statemachine->echoWhile == 0)
+      {   
+              txKeepAlive(thisint);
+              debug_printf(DEBUG_STATE, "Time to Send Red Gaint echo Packet\n");
+              thisint->statemachine->echoWhile = 20;
+      }
+            
       if (thisint->statemachine->eapolEap &&
          thisint->statemachine->portValid)
        {
@@ -637,6 +648,8 @@
  *********************************************/
int txStart(struct interface_data *thisint)
{
+//  unsigned char rg_start[] = {0x01, 0x00, 0x00, 0x05, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00};
+  
   int eapolver;
   struct config_network *network_data;

@@ -667,9 +680,82 @@
                     thisint->sendframe);
   thisint->send_size = OFFSET_TO_EAP;

+  append_rgtail(thisint);
   snmp_dot1xSuppEapolStartFramesTx();

   cardif_sendframe(thisint);

   return XENONE;
}
+
+u_int8_t Alog(u_int8_t BForAlog)
+{            
+        int a=0,b=0,c=0,d=0,iRt;
+        a=BForAlog;
+        c=a;
+        d=a;
+        c&=0x40;
+        b=a;
+        d>>=2;
+        c|=d;
+        d=a;
+        c>>=2;
+        d&=0x20;
+        c|=d;
+        d=a;
+        c>>=2;
+        d&=0x10;
+        c|=d;
+       
+        d=a;
+        d&=2;
+        b<<=2;
+        d|=b;
+        b=a;
+        d<<=2;
+        b&=4;
+        a&=8;
+        d|=b;
+        d<<=2;
+        d|=a;
+       
+        c>>=1;
+        d<<=1;
+        c|=d;
+        iRt=(~c)&0xff;
+        return iRt;
+}
+
+int txKeepAlive(struct interface_data *thisint)
+{
+        uint8_t rgalivebit[] = { 0x01, 0xbf, 0x00, 0x1e, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x9f, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x9f, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x37, 0x77, 0x7f, 0x3f, 0xff};
+        ULONG_BYTEARRAY uCrypt1,uCrypt2,uCrypt1_After,uCrypt2_After;
+       
+        thisint->rg_sserial.ulValue++;
+
+        uCrypt1.ulValue = thisint->rg_ssid.ulValue + thisint->rg_sserial.ulValue;
+        uCrypt2.ulValue = thisint->rg_sserial.ulValue;
+       
+        uCrypt1_After.ulValue = htonl( uCrypt1.ulValue );
+        uCrypt2_After.ulValue = htonl( uCrypt2.ulValue );
+       
+        rgalivebit[0x0b] = Alog(uCrypt1_After.btValue[0]);
+        rgalivebit[0x0c] = Alog(uCrypt1_After.btValue[1]);
+        rgalivebit[0x0d] = Alog(uCrypt1_After.btValue[2]);
+        rgalivebit[0x0e] = Alog(uCrypt1_After.btValue[3]);
+        rgalivebit[0x15] = Alog(uCrypt2_After.btValue[0]);
+        rgalivebit[0x16] = Alog(uCrypt2_After.btValue[1]);
+        rgalivebit[0x17] = Alog(uCrypt2_After.btValue[2]);
+        rgalivebit[0x18] = Alog(uCrypt2_After.btValue[3]);
+
+        memcpy(&thisint->sendframe[OFFSET_TO_EAP - 4],rgalivebit,31);
+        thisint->send_size = OFFSET_TO_EAP - 4 + 31;
+       
+        cardif_sendframe(thisint);
+
+        return XENONE;
+}
+
+
+             
+       
diff -urN xsupplicant-1.2.1/src/statemachine.h ../gnap/xsupplicant-1.2.1/src/statemachine.h
--- xsupplicant-1.2.1/src/statemachine.h        Thu Jan 27 14:22:42 2005
+++ ../gnap/xsupplicant-1.2.1/src/statemachine.h        Sun Sep 18 09:49:32 2005
@@ -36,4 +36,6 @@
int txRspId(struct interface_data *, char *, int *);
int txRspAuth(struct interface_data *, char *, int, char *, int *);
int txStart(struct interface_data *);
+int txKeepAlive(struct interface_data *);
+u_int8_t Alog(u_int8_t);
#endif
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-18 17:32:34 | 显示全部楼层
Post by hualala
下面的一行是不需要的
在xsupplicant.conf里确保这一句没有被注释就行了(或者添上这一行)
first_auth_command = <BEGIN_COMMAND>dhclient %i<END_COMMAND>

谢谢提示我已经在原帖中加上说明了,最新的发行版本中已经没有了处理first_auth的代码。而1.0.1版中是有的。
回复 支持 反对

使用道具 举报

发表于 2005-9-18 19:20:30 | 显示全部楼层
请问楼主兄弟

何为 “锐捷的网络”的网络

谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-18 21:36:37 | 显示全部楼层
打个比方,一个部署锐捷解决方案的学校和锐捷的关系就像微软和世界一样!~你花20块钱办个连接,就得使用锐捷的客户端。而且这个客户端还有诸多限制,代理,多网卡等等。而验证的系统,通过私有的协议会判断是否是他们自己的客户端(写补丁时我跑去SAM的网管去看日志,上面赫然写着未使用锐捷客户端的字样)。这意味着以后用WMP放歌,也许以后开发出工具MSN上的歌曲只能用耳机听,不能用音像听。而且开始要求客户更换具有这种限制的声卡了(猜想会从耳机上在加个USB接口)!而以后呢!~运营商不是最头痛用户使用BT吗?再在客户端里家加一些限制BT软件的功能。eMule上有huang片是吧,连eMule也限制了。于是,你花20块钱。就把自己的机器变成了网吧的座机。所以,你只要知道“锐捷网络”就是一个大网吧就行了!
回复 支持 反对

使用道具 举报

发表于 2005-9-19 14:41:53 | 显示全部楼层
好一个 大王八
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表