<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>apt-blog.net    IT民工养成计划    PT博客 &#187; 神州数码</title>
	<atom:link href="http://apt-blog.net/tag/%e7%a5%9e%e5%b7%9e%e6%95%b0%e7%a0%81/feed" rel="self" type="application/rss+xml" />
	<link>http://apt-blog.net</link>
	<description>以我多年种田的经验来看，什么都略懂一点，生活才多彩一点……猪葛亮说的……</description>
	<lastBuildDate>Mon, 23 Aug 2010 10:45:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>锐捷/联想/神州数码 802.1x客户端支持MacOS、BSD</title>
		<link>http://apt-blog.net/802-1x_support_macos_freebsd</link>
		<comments>http://apt-blog.net/802-1x_support_macos_freebsd#comments</comments>
		<pubDate>Fri, 09 Oct 2009 05:32:23 +0000</pubDate>
		<dc:creator>BOYPT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[BSD]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MacOS]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[联想]]></category>
		<category><![CDATA[锐捷]]></category>
		<guid isPermaLink="false">http://apt-blog.net/?p=656</guid>
		<description><![CDATA[Insion同学之前发来一段可以在MacOS/BSD编译运行获取网卡MAC地址的代码，于是整理了一下，让几个802.1x Client都能支持MacOS/BSD了。 下载了个FreeBSD 7.2在vbox虚拟机里面装了下，发现FreeBSD比Linux好像原始多了［呃，我说安装程序］，分区的时候他不叫Create Partition，叫Create Slice，我对着界面看了半天才猜到，囧；退出那里写着：Q = Finish，Quit就Quit嘛，什么Finish，纠结……但还好，其他的配置跟Linux还是很相像的，调试了一下就有了全可编译的代码了。 代码部分修改倒没多少，就添加了一个专门给BSD系系统获取MAC的函数，再用maroc判断一下，以及几个头文件，就完事了，有点麻烦的是makefile，发现freebsd默认那个make好像是很古老很古老的版本，我程序里面那个Makefile是用了vim里面c-support插件里面带的Makefile模板，有点复杂，但是freebsd居然不支持！所以整理了个简单的版本，专门给MacOS/BSD编译，也方便别人的修改；另外一个原因是，程序里面转换服务器消息时候用了iconv库，linux里面iconv是系统内嵌库来的，用不着链接的时候给出参数，但MacOS/BSD偏偏就要-liconv…… 需要编译MacOS/BSD版本的同学，可以check出项目里面trunk的代码，运行make -f Makefile.bsd来编译。Insion同学已经编译成功，而且在他的主页上有二进制版下载了。 相对的说，可能在MacOS里面编译是最麻烦的，我大概说说流程（实际上我没试过，我可没Mac机器［T.T］） 1.安装gcc，参考这里从http://connect.apple.com/的Dev Tools里面下载Xcode Tools，安装。2.编译安装libpcap，从http://www.tcpdump.org/release/libpcap-1.0.0.tar.gz下载源码，tar xvfz libpcap-1.0.0.tar.gz解压，进去该目录，./configure、make、make install安装完成；3.编译802.1x客户端，从所用项目内签出源码，在目录内make，没出什么差错的话，已经完成了。然后按Readme.txt的方法安装运行，即可！ 项目主页 锐捷：http://code.google.com/p/zruijie4gzhu/联想：http://code.google.com/p/zlevoclient/神州数码：http://code.google.com/p/zdcclient/]]></description>
			<content:encoded><![CDATA[<p>Insion同学之前发来一段可以在MacOS/BSD编译运行获取网卡MAC地址的代码，于是整理了一下，让几个802.1x Client都能支持MacOS/BSD了。</p>
<p>下载了个FreeBSD 7.2在vbox虚拟机里面装了下，发现FreeBSD比Linux好像原始多了［呃，我说安装程序］，分区的时候他不叫Create Partition，叫Create Slice，我对着界面看了半天才猜到，囧；退出那里写着：Q = Finish，Quit就Quit嘛，什么Finish，纠结……但还好，其他的配置跟Linux还是很相像的，调试了一下就有了全可编译的代码了。</p>
<p>代码部分修改倒没多少，就添加了一个专门给BSD系系统获取MAC的函数，再用maroc判断一下，以及几个头文件，就完事了，有点麻烦的是makefile，发现freebsd默认那个make好像是很古老很古老的版本，我程序里面那个Makefile是用了vim里面c-support插件里面带的Makefile模板，有点复杂，但是freebsd居然不支持！所以整理了个简单的版本，专门给MacOS/BSD编译，也方便别人的修改；另外一个原因是，程序里面转换服务器消息时候用了iconv库，linux里面iconv是系统内嵌库来的，用不着链接的时候给出参数，但MacOS/BSD偏偏就要-liconv……</p>
<p>需要编译MacOS/BSD版本的同学，可以check出项目里面trunk的代码，运行make -f Makefile.bsd来编译。Insion同学已经编译成功，而且在<a target="_blank" href="http://garning.com/forever/68_garning_%E7%A5%9E%E5%B7%9E%E6%95%B0%E7%A0%81-for-mac-%EF%BC%88interpowerpcbsd%EF%BC%89_garning.html">他的主页上有二进制版</a>下载了。</p>
<p>相对的说，可能在MacOS里面编译是最麻烦的，我大概说说流程（实际上我没试过，我可没Mac机器［T.T］）</p>
<p>1.安装gcc，参考<a target="_blank" href="http://www.tech-recipes.com/rx/726/mac-os-x-install-gcc-compiler/">这里</a>从<a target="_blank" href="http://connect.apple.com/">http://connect.apple.com/</a>的Dev Tools里面下载Xcode Tools，安装。<br />2.编译安装libpcap，从<a target="_blank" href="http://www.tcpdump.org/release/libpcap-1.0.0.tar.gz">http://www.tcpdump.org/release/libpcap-1.0.0.tar.gz</a>下载源码，tar xvfz libpcap-1.0.0.tar.gz解压，进去该目录，./configure、make、make install安装完成；<br />3.编译802.1x客户端，从所用项目内签出源码，在目录内make，没出什么差错的话，已经完成了。然后按Readme.txt的方法安装运行，即可！</p>
<p>项目主页</p>
<p>锐捷：<a target="_blank" href="http://code.google.com/p/zruijie4gzhu/">http://code.google.com/p/zruijie4gzhu/</a><br />联想：<a target="_blank" href="http://code.google.com/p/zlevoclient/">http://code.google.com/p/zlevoclient/</a><br />神州数码：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/802-1x_support_macos_freebsd/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>深入了解校园网802.1x认证的EAP协议(2)——神州数码认证细节</title>
		<link>http://apt-blog.net/eap_explaination_2</link>
		<comments>http://apt-blog.net/eap_explaination_2#comments</comments>
		<pubDate>Sat, 04 Jul 2009 15:13:44 +0000</pubDate>
		<dc:creator>BOYPT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAP]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/?p=452</guid>
		<description><![CDATA[各地的校园网认证有很多种品牌，正因为EAP可扩展的特点，基本上每个品牌的认证方案都会互不相同。从商业角度考虑，当使用了某个品牌的认证系统后，很可能就不能使用其他牌子的交换机了；而对用户来说，这不仅带来了以后维护的问题，还因为各个厂商开发的EAP客户端的投入不同，质量良莠不齐，占用内存大、限制多（比如有些为了防止用户开代理，加入多网卡检测，结果用户就不能使用虚拟机、手机GPRS Modem等）、不支持非Win平台。 这就是我们研究这些厂商自定义的EAP协议的意义。 PT实现的神州数码Linux客户端项目主页：http://code.google.com/p/zdcclient/ 以下的说明是基于EAP协议过程的补充描述，如果不清楚EAP，可先读深入了解校园网802.1x认证的EAP协议(1)——EAP的总体流程。 神州数码的私有信息尾结构神州数码协议里面最特别的地方是有一段46字节的信息，其位于EAP报文后，属于EAPOL报文的尾端部分，在发往服务器的EAP_RESPONSE_IDENTITY和EAP_RESPONSE_MD5_Challenge两种报文里面都需要附上该46字节的信息以供验证。 在PT的神州数码验证程序zdclient里面，zdclient.h定义了这个信息结构： struct dcba_tailer &#123; bpf_u_int32 local_ip; bpf_u_int32 local_mask; bpf_u_int32 local_gateway; bpf_u_int32 local_dns; u_char username_md5&#91;16&#93;; u_char client_ver&#91;13&#93;; &#125;; local_ip 4字节 本机IP local_mask 4字节 本机掩码 local_gateway 4字节 本机网关 local_dns 4字节 本机DNS服务器 username_md5 16字节 用户名的MD5值 client_ver 13字节 客户端版本号ASCII码 当然这个结构体只有45字节，实际上在其附到EAP报文时，46字节的首字节用以表示认证所使用的DHCP模式，但由于其加入到上面这个结构体中会引起内存对齐问题，所以暂且让这个DHCP位不属于这个结构。 DHCP位只有0和非0两个状态，前者表示静态，非DHCP模式，后者则是DHCP模式。 这里所谓的DHCP模式并不跟操作系统给网卡获得IP那个DHCP概念等价。在常见的DHCP模式中，完成了认证之后需要重新运行dhclient之类的DHCP客户端来更新网卡的IP，但实际上并不一定如此，实际上是否需要更新得看具体环境，比如广州大学这里，我们需要让程序以DHCP模式认证，但并不需要更新IP，因为系统启动后已经自动获得了。 在不同的验证系统，对信息体的校验的严紧度也不同（估计在服务器可配置）。一般静态IP模式下，需要正确的local_ip段来验证用户是否属于特定子网、端口，但是在动态DHCP模式下，在认证之前网卡是没有合法IP的，因此可以模仿Windows系统发送一个169.254.x.x的伪IP。至于网关和DNS地址，在实际使用中发现填不填影响不大，可留为0。用户名MD5就是用户名字符串的16字节MD5值；剩下的13字节则是包含认证客户端的版本号信息，也是一个普通的字符串，目前已知的版本号包括`3.5.04.1013fk'、`3.5.04.1110fk'、`3.5.04.0324'等……有些网络环境会验证这个字符串，如果客户端版本不合适，就发出相应警告，比如目前武汉大学的认证系统只能使用`3.5.04.1013fk'、`3.5.04.1110fk'两个比较新的版本号来登录，但此前广州大学的神数系统对版本号通吃。 程序里面对这个结构的初始化代码是这样的： u_char local_info_tailer&#91;46&#93; = &#123;0&#125;; &#160; local_info_tailer&#91;0&#93; = dhcp_on; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>各地的校园网认证有很多种品牌，正因为EAP可扩展的特点，基本上每个品牌的认证方案都会互不相同。从商业角度考虑，当使用了某个品牌的认证系统后，很可能就不能使用其他牌子的交换机了；而对用户来说，这不仅带来了以后维护的问题，还因为各个厂商开发的EAP客户端的投入不同，质量良莠不齐，占用内存大、限制多（比如有些为了防止用户开代理，加入多网卡检测，结果用户就不能使用虚拟机、手机GPRS Modem等）、不支持非Win平台。</p>
<p>这就是我们研究这些厂商自定义的EAP协议的意义。</p>
<p>PT实现的神州数码Linux客户端项目主页：<a href="http://code.google.com/p/zdcclient/" target="_blank">http://code.google.com/p/zdcclient/</a></p>
<p>以下的说明是基于EAP协议过程的补充描述，如果不清楚EAP，可先读<a href="../archives/423.html">深入了解校园网802.1x认证的EAP协议(1)——EAP的总体流程</a>。</p>
<p>神州数码的私有信息尾结构神州数码协议里面最特别的地方是有一段46字节的信息，其位于EAP报文后，属于EAPOL报文的尾端部分，在发往服务器的EAP_RESPONSE_IDENTITY和EAP_RESPONSE_MD5_Challenge两种报文里面都需要附上该46字节的信息以供验证。<span id="more-452"></span></p>
<p>在PT的神州数码验证程序zdclient里面，zdclient.h定义了这个信息结构：</p>
<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> dcba_tailer <span style="color: #009900;">&#123;</span>
    bpf_u_int32     local_ip<span style="color: #339933;">;</span>
    bpf_u_int32     local_mask<span style="color: #339933;">;</span>
    bpf_u_int32     local_gateway<span style="color: #339933;">;</span>
    bpf_u_int32     local_dns<span style="color: #339933;">;</span>
    u_char          username_md5<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    u_char          client_ver<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">13</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>
<table style="border: 3px none ; width: 425px;" border="0">
<tbody>
<tr>
<td>local_ip</td>
<td style="vertical-align: top;"></td>
<td>4字节</td>
<td>本机IP</td>
</tr>
<tr>
<td>local_mask</td>
<td style="vertical-align: top;"></td>
<td>4字节</td>
<td>本机掩码</td>
</tr>
<tr>
<td>local_gateway</td>
<td style="vertical-align: top;"></td>
<td>4字节</td>
<td>本机网关</td>
</tr>
<tr>
<td>local_dns</td>
<td style="vertical-align: top;"></td>
<td>4字节</td>
<td>本机DNS服务器</td>
</tr>
<tr>
<td>username_md5</td>
<td style="vertical-align: top;"></td>
<td>16字节</td>
<td>用户名的MD5值</td>
</tr>
<tr>
<td>client_ver</td>
<td style="vertical-align: top;"></td>
<td>13字节</td>
<td>客户端版本号ASCII码</td>
</tr>
</tbody>
</table>
<p>当然这个结构体只有45字节，实际上在其附到EAP报文时，46字节的首字节用以表示认证所使用的DHCP模式，但由于其加入到上面这个结构体中会引起内存对齐问题，所以暂且让这个DHCP位不属于这个结构。</p>
<p>DHCP位只有0和非0两个状态，前者表示静态，非DHCP模式，后者则是DHCP模式。</p>
<p>这里所谓的DHCP模式并不跟操作系统给网卡获得IP那个DHCP概念等价。在常见的DHCP模式中，完成了认证之后需要重新运行dhclient之类的DHCP客户端来更新网卡的IP，但实际上并不一定如此，实际上是否需要更新得看具体环境，比如广州大学这里，我们需要让程序以DHCP模式认证，但并不需要更新IP，因为系统启动后已经自动获得了。</p>
<p>在不同的验证系统，对信息体的校验的严紧度也不同（估计在服务器可配置）。一般静态IP模式下，需要正确的local_ip段来验证用户是否属于特定子网、端口，但是在动态DHCP模式下，在认证之前网卡是没有合法IP的，因此可以模仿Windows系统发送一个169.254.x.x的伪IP。至于网关和DNS地址，在实际使用中发现填不填影响不大，可留为0。用户名MD5就是用户名字符串的16字节MD5值；剩下的13字节则是包含认证客户端的版本号信息，也是一个普通的字符串，目前已知的版本号包括`3.5.04.1013fk'、`3.5.04.1110fk'、`3.5.04.0324'等……有些网络环境会验证这个字符串，如果客户端版本不合适，就发出相应警告，比如目前武汉大学的认证系统只能使用`3.5.04.1013fk'、`3.5.04.1110fk'两个比较新的版本号来登录，但此前广州大学的神数系统对版本号通吃。</p>
<p>程序里面对这个结构的初始化代码是这样的：</p>
<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    u_char local_info_tailer<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">46</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    local_info_tailer<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> dhcp_on<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #993333;">struct</span> dcba_tailer <span style="color: #339933;">*</span>dcba_info_tailer <span style="color: #339933;">=</span>
                <span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> dcba_tailer <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>local_info_tailer <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    dcba_info_tailer<span style="color: #339933;">-&gt;</span>local_ip          <span style="color: #339933;">=</span> local_ip<span style="color: #339933;">;</span>
    dcba_info_tailer<span style="color: #339933;">-&gt;</span>local_mask        <span style="color: #339933;">=</span> local_mask<span style="color: #339933;">;</span>
    dcba_info_tailer<span style="color: #339933;">-&gt;</span>local_gateway     <span style="color: #339933;">=</span> local_gateway<span style="color: #339933;">;</span>
    dcba_info_tailer<span style="color: #339933;">-&gt;</span>local_dns         <span style="color: #339933;">=</span> local_dns<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #993333;">char</span><span style="color: #339933;">*</span> username_md5 <span style="color: #339933;">=</span> get_md5_digest<span style="color: #009900;">&#40;</span>username<span style="color: #339933;">,</span> username_length<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    memcpy <span style="color: #009900;">&#40;</span>dcba_info_tailer<span style="color: #339933;">-&gt;</span>username_md5<span style="color: #339933;">,</span> username_md5<span style="color: #339933;">,</span> <span style="color: #0000dd;">16</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    free <span style="color: #009900;">&#40;</span>username_md5<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    strncpy <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>dcba_info_tailer<span style="color: #339933;">-&gt;</span>client_ver<span style="color: #339933;">,</span> client_ver<span style="color: #339933;">,</span> <span style="color: #0000dd;">13</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>
<p>然后我们构建一个IDENTITY报文。帧的目的地址是802.1x标准的多播地址01-80-c2-00-00-03（这里没登出Ether帧头部信息）。</p>
<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    u_char eap_resp_iden_head<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">9</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #208080;">0x01</span><span style="color: #339933;">,</span> <span style="color: #208080;">0x00</span><span style="color: #339933;">,</span>
                                    <span style="color: #208080;">0x00</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">46</span> <span style="color: #339933;">+</span> username_length<span style="color: #339933;">,</span>  <span style="color: #808080; font-style: italic;">/* eapol_length */</span>
                                    <span style="color: #208080;">0x02</span><span style="color: #339933;">,</span> <span style="color: #208080;">0x01</span><span style="color: #339933;">,</span>
                                    <span style="color: #208080;">0x00</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5</span> <span style="color: #339933;">+</span> username_length<span style="color: #339933;">,</span>       <span style="color: #808080; font-style: italic;">/* eap_length */</span>
                                    <span style="color: #208080;">0x01</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    eap_response_ident <span style="color: #339933;">=</span> malloc <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">14</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">9</span> <span style="color: #339933;">+</span> username_length <span style="color: #339933;">+</span> <span style="color: #0000dd;">46</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    data_index <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//以太网帧头</span>
    memcpy <span style="color: #009900;">&#40;</span>eap_response_ident <span style="color: #339933;">+</span> data_index<span style="color: #339933;">,</span> eapol_eth_header<span style="color: #339933;">,</span> <span style="color: #0000dd;">14</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    data_index <span style="color: #339933;">+=</span> <span style="color: #0000dd;">14</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//EAP帧头</span>
    memcpy <span style="color: #009900;">&#40;</span>eap_response_ident <span style="color: #339933;">+</span> data_index<span style="color: #339933;">,</span> eap_resp_iden_head<span style="color: #339933;">,</span> <span style="color: #0000dd;">9</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    data_index <span style="color: #339933;">+=</span> <span style="color: #0000dd;">9</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//用户名</span>
    memcpy <span style="color: #009900;">&#40;</span>eap_response_ident <span style="color: #339933;">+</span> data_index<span style="color: #339933;">,</span> username<span style="color: #339933;">,</span> username_length<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    data_index <span style="color: #339933;">+=</span> username_length<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//尾信息</span>
    memcpy <span style="color: #009900;">&#40;</span>eap_response_ident <span style="color: #339933;">+</span> data_index<span style="color: #339933;">,</span> local_info_tailer<span style="color: #339933;">,</span> <span style="color: #0000dd;">46</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>
<p>分别把以太网报文头、EAP头、用户名、信息尾复制到一个数组内，这就是我们最后要发送的报文了。</p>
<p>不过观察神州官方版客户端发出的报文，DCBA信息体并不一定总紧跟eap报文，其在RESPONSE MD5 Challenge 报文里面就基本位于报文的最后，开始于0xa8，中间留空了一大堆0。在zdclient里面没有这样处理，一样紧跟在eap报文后。</p>
<p>注意EAPOL和EAP的长度字段，如果不算46字节的信息尾，它们是相等的，这在解释EAP报文时候提到过。</p>
<p>当成功认证了之后，服务器大概每隔20多秒会重新发来一个REQUEST IDENTITY报文，这个REQUEST IDENTITY和认证过程中的REQUEST IDENTITY只有一个字节的差别，就是eap_id字段，认证时为0x01，保鲜阶段为0x03，zdclient里面对两个报文使用同一个缓冲区，加了个hack，发保鲜报文时候就把这个位置改成0x03。</p>
<p>整个EAP认证过程中需要发出去的报文也只有四种，至于剩下的两个START和OFF，都只有几个字节，不涉及神州数码的信息尾字段，跟标准里面一样。</p>
<h3>服务器的反馈信息</h3>
<p>我们除了构建这些发出去的报文外，其实对服务器返回的信息兴趣不大，因为只需要判断其中的几个状态位，就知道下一步该干什么了。但是神州数码的反馈报文里面通常除了这些信息尾外，在SUCCESS和FAILURE报文里面通常都会包含一段中文文字，告诉用户是什么问题或者什么通知。</p>
<p>这些信息PT是通过盯着抓来的报文盯出来的，因为其使用GB2312编码的中文，通常使用含高位的ASCII值，看到一堆数值都大于0x80，尝试着放到Python里面按GBK解码，才发现的。</p>
<p>用来搜索报文内的中文信息的python函数：</p>
<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> searchgbk<span style="color: black;">&#40;</span>byte_array<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span> <span style="color: black;">&#40;</span>byte_array<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;[%02x] %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>i, byte_array<span style="color: black;">&#91;</span>i:<span style="color: black;">&#93;</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gbk'</span>, <span style="color: #483d8b;">'ignore'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>
<p>最后总结出中文信息的规律：<br />
<span style="font-family: monospace;">在报文的特定位置出现0x12的首导符，紧跟着一个字节表示该信息的长度，之后便是该信息。0x12出现的位置有：<span style="font-weight: bold;">[0x2A]、[0x42]、[0x9A]、[0x120]</span></span></p>
<p>最后的完整过程可见print_server_info函数的实现，print_server_info获得字符串的地址后送入转码函数，由iconv的API转换成UTF-8编码的字符串后才由printf输出。</p>
<h3>zdclient的报文“驱动式”实现</h3>
<p>回顾神州数码协议的整个流程，可知基本上客户端基本上都是在服务器发来了请求报文之后才需要发出应答报文（颇有颠倒了客户-服务角色的意味），其实这样对验证服务器的压力挺大的，不过这不关我们事，而且这也方便了我们对客户端程序的设计。所以zdclient采用了“报文驱动式”的流程，就是说，除了一开始发送一个上线请求，以后接收到什么就应答什么，其他时间一直在无限循环里面loop，睡觉。</p>
<p>libpcap提供了回呼(callback)机制，就是设定了某个回呼函数，只有当网卡接收到特定报文时候才进行中断响应。zdclient里面的get_packet函数就是回呼函数，所有工作都是有它驱动完成的。希望这一点有助于阅读和以后再次开发zdclient的朋友理解代码。</p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/eap_explaination_2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ZDClient 0.5版发布</title>
		<link>http://apt-blog.net/zdclient_0-5_release</link>
		<comments>http://apt-blog.net/zdclient_0-5_release#comments</comments>
		<pubDate>Fri, 22 May 2009 13:44:03 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAPOL]]></category>
		<category><![CDATA[客户端]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/383.html</guid>
		<description><![CDATA[改善DHCP模式下的认证IP处理方法：若程序能够从网卡获得IP，则使用网卡的真实IP只有获取不到IP时才使用伪IP 169.254.216.45 在使用伪IP的情况下，当接受到第一个REQUEST IDT KEEP ALIVE报文后，尝试再次获取网卡IP与MASK并写入RESPONSE数据帧缓冲区替换伪IP，之后发出的RESPONSE数据帧将包含真实IP 只有当用户同时指定了IP和MASK才使用用户设定值，否则由程序处理IP 修正一些stderr、stderr的滥用 使用起来应该没太大变化，只是让协议更接近官方客户端的过程。现在主页上同时有二进制包和源代码包下载。 项目主页：http://code.google.com/p/zdcclient/ 连续一个星期每天一个版本，= .=有点不可思议的说……]]></description>
			<content:encoded><![CDATA[<ul>
<li>改善DHCP模式下的认证IP处理方法：<br />若程序能够从网卡获得IP，则使用网卡的真实IP<br />只有获取不到IP时才使用伪IP 169.254.216.45</li>
<li>在使用伪IP的情况下，当接受到第一个REQUEST IDT KEEP ALIVE报文后，尝试再次获取网卡IP与MASK并写入RESPONSE数据帧缓冲区替换伪IP，之后发出的RESPONSE数据帧将包含真实IP</li>
<li>只有当用户同时指定了IP和MASK才使用用户设定值，否则由程序处理IP</li>
<li>修正一些stderr、stderr的滥用</li>
</ul>
<p>使用起来应该没太大变化，只是让协议更接近官方客户端的过程。现在主页上同时有二进制包和源代码包下载。</p>
<p>项目主页：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a></p>
<p>连续一个星期每天一个版本，= .=有点不可思议的说……</p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/zdclient_0-5_release/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZDClient升级到0.4，完善DHCP模式的认证</title>
		<link>http://apt-blog.net/zdclient_0-4_release</link>
		<comments>http://apt-blog.net/zdclient_0-4_release#comments</comments>
		<pubDate>Thu, 21 May 2009 04:29:20 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAPOL]]></category>
		<category><![CDATA[客户端]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/377.html</guid>
		<description><![CDATA[神州数码客户端ZDClient升级到0.4，完善DHCP模式的认证 经过跟武汉大学的michel同学不断的折腾和测试，终于搞清楚他们学校动态DHCP的流程了，“Windows启动后，提示本地连接受限”，到认证后才开始获取IP，这才是动态DHCP模式，所以使用ZDClient的dhcp后，需要运行系统的DHCP客户端重新获取一次IP（通常是dhclient），这一点功能在启动脚本dhcp_zdc_run.sh内已经包含。 现在在Google Code上面的项目已经正式启动，终于用上svn的服务器了，不用把桌面搞的一团糟。 大家可从项目主页下载最新的源码包：http://code.google.com/p/zdcclient/ 之前的网盘链接已经作废。 特别感谢一下刘群同学的关注，给我编译i386的binary，我似乎终于搞定在amd64使用32位的包了！]]></description>
			<content:encoded><![CDATA[<p>神州数码客户端ZDClient升级到0.4，完善DHCP模式的认证</p>
<p>经过跟武汉大学的michel同学不断的折腾和测试，终于搞清楚他们学校动态DHCP的流程了，“Windows启动后，提示本地连接受限”，到认证后才开始获取IP，这才是动态DHCP模式，所以使用ZDClient的dhcp后，需要运行系统的DHCP客户端重新获取一次IP（通常是dhclient），这一点功能在启动脚本dhcp_zdc_run.sh内已经包含。</p>
<p>现在在Google Code上面的项目已经正式启动，终于用上svn的服务器了，不用把桌面搞的一团糟。</p>
<p>大家可从项目主页下载最新的源码包：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a></p>
<p>之前的网盘链接已经作废。</p>
<p>特别感谢一下<cite>刘群</cite>同学的关注，给我编译i386的binary，我似乎终于搞定在amd64使用32位的包了！</p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/zdclient_0-4_release/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>神州数码客户端ZDClient升级到0.3，支持武汉大学的校园网</title>
		<link>http://apt-blog.net/zdclient_0-3_release</link>
		<comments>http://apt-blog.net/zdclient_0-3_release#comments</comments>
		<pubDate>Wed, 20 May 2009 06:56:27 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAPOL]]></category>
		<category><![CDATA[客户端]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/374.html</guid>
		<description><![CDATA[0.3更新-客户端默认版本号更新为3.5.04.1013fk-修正对SUCCESS数据包的识别-后台运行改为在认证成功后主程序返回-根据状态区分用户名、用户配置信息错误与密码错误的两种提示-在接收和发送Keep Alive报文时提示当前线程的pid-改善pcap的抓包过滤器，只抓发往本机的报文 在姚老大的群里面找到武汉大学的同学micheal帮忙测试了ZDClient，昨天晚上把他们的官方客户端的数据包抓了过来看，原来版本是3.5.04.1013fk，比我们的新！不过奇怪的是广州大学的认证服务器除了用户名密码别的似乎什么都不认证，我怎么乱填都能认证成功 = .= 顺便提醒一下武大的同学，记得在zdcrun里面加上--dhcp参数…… 大家可从项目主页下载最新的源码包：http://code.google.com/p/zdcclient/]]></description>
			<content:encoded><![CDATA[<p>0.3更新<br />-客户端默认版本号更新为3.5.04.1013fk<br />-修正对SUCCESS数据包的识别<br />-后台运行改为在认证成功后主程序返回<br />-根据状态区分用户名、用户配置信息错误与密码错误的两种提示<br />-在接收和发送Keep Alive报文时提示当前线程的pid<br />-改善pcap的抓包过滤器，只抓发往本机的报文</p>
<p>在姚老大的群里面找到武汉大学的同学micheal帮忙测试了ZDClient，昨天晚上把他们的官方客户端的数据包抓了过来看，原来版本是3.5.04.1013fk，比我们的新！不过奇怪的是广州大学的认证服务器除了用户名密码别的似乎什么都不认证，我怎么乱填都能认证成功    = .=</p>
<p>顺便提醒一下<span style="font-weight: bold;">武大</span>的同学，记得在zdcrun里面加上--dhcp参数……</p>
<p>大家可从项目主页下载最新的源码包：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a><a target="_blank" href="http://www.box.net/shared/rl2t714rim"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/zdclient_0-3_release/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>神州数码客户端ZDClient升级到0.2</title>
		<link>http://apt-blog.net/zdclient_0-2_release</link>
		<comments>http://apt-blog.net/zdclient_0-2_release#comments</comments>
		<pubDate>Tue, 19 May 2009 12:08:53 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAPOL]]></category>
		<category><![CDATA[客户端]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/372.html</guid>
		<description><![CDATA[今天对比了官方拨号器的报文，改进了一下包分析流程。广州大学的方案似乎做很少校验，有些东西乱填都照样能过。同时也把协议版本修改到3.5版本的，之前在Wiki页有武汉大学的同学求助说他们学校的神州数码因为3.5的版本校验没法使用姚琪的版本，在这里召唤武汉大学的同学来帮忙测试ZDClient了，哈哈。 0.2 更新-整理代码-进一步完善包解析、发送过程细节，加入遇到为止包时的提示-区分EAP_RESPONSE_IDENTITY和EAP_RESPONSE_IDENTITY_KEEP_ALIVE发送的包-加入自定义客户端版本号的功能参数--ver，并能校验版本号长度-默认版本号改成3.5.04.0324-修改--help内About ZDClient的文字-在认证是提示协议版本信息-增加可检测root权限的启动脚本 大家可从项目主页下载最新的源码包：http://code.google.com/p/zdcclient/]]></description>
			<content:encoded><![CDATA[<p>今天对比了官方拨号器的报文，改进了一下包分析流程。广州大学的方案似乎做很少校验，有些东西乱填都照样能过。同时也把协议版本修改到3.5版本的，之前在Wiki页有武汉大学的同学求助说他们学校的神州数码因为3.5的版本校验没法使用姚琪的版本，在这里召唤武汉大学的同学来帮忙测试ZDClient了，哈哈。</p>
<p>0.2 更新<br />-整理代码<br />-进一步完善包解析、发送过程细节，加入遇到为止包时的提示<br />-区分EAP_RESPONSE_IDENTITY和EAP_RESPONSE_IDENTITY_KEEP_ALIVE发送的包<br />-加入自定义客户端版本号的功能参数--ver，并能校验版本号长度<br />-默认版本号改成3.5.04.0324<br />-修改--help内About ZDClient的文字<br />-在认证是提示协议版本信息<br />-增加可检测root权限的启动脚本</p>
<p>大家可从项目主页下载最新的源码包：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/zdclient_0-2_release/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>神州数码802.1x认证的C语言版客户端</title>
		<link>http://apt-blog.net/digital_china_802-1x_client</link>
		<comments>http://apt-blog.net/digital_china_802-1x_client#comments</comments>
		<pubDate>Mon, 18 May 2009 14:36:03 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAPOL]]></category>
		<category><![CDATA[客户端]]></category>
		<category><![CDATA[神州数码]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/368.html</guid>
		<description><![CDATA[一直以来在Linux下要接入神州数码认证用的是姚琦开发的Java版认证工具，不过现在起，使用神码的同学可以把jvm抛弃啦！PT开发出了C语言版的神州数码802.1x客户端！ 项目主页：http://code.google.com/p/zdcclient/ 开发手记 PT的客户端版本虽然是命令行的版本，但是功能和姚琦的Java版功能没多大差别，目前支持自定义接入网卡、支持DHCP、支持程序运行后自动fork到后台，用户名等通过参数传入程序。 Java版的软件虽然一般使用起来没太大区别，但是当系统中没有jvm虚拟机和软件依赖的库，而且电脑又不能上网的时候，这可是相当棘手的问题，我去年就为此在Ubuntu-cn的Wiki写了一篇教程，如何从源里面抓jvm的一堆包回来安装，再折腾一番才能用。况且Java程序占的资源颇大，就那个0.6.1版的客户端，常驻内存有50M！ 姚琦的个人网站上面公布了他的客户端软件的源码，之前有下载回来，不过一直没看，早天兴起把文件重新放到Netbeans里面来编译一次，发现能编译却不能认证！好奇之下跟踪了其代码，把带界面的1500多行的程序删减到只剩400行的命令行程序，然后再根据抓数据包的对比，发现是这个版本获取本机地址的代码有问题，在Linux下获取本机IP是错的，这样组成的数据包去认证，当然不行了，具体在这里有人解释。 摸清楚认证过程的来龙去脉后，就打算自己用C来写一个客户端，虽然我有2G内存，但老被占着几十M也不舒服。Java里面用的jpcap，是Java用JNI对libpcap的封装，之前我弄过编译amd64版时候接触过，发现其功能很强大，使用也不复杂，于是对写个原生C语言版的客户端也有了信心。 为了弄清整个程序的工作流程，我进一步优化了Java版的代码，400多行最后剩下200多了，姚学长的编码好像有点太过那个，呃……而且姚学长好像连jpcap的toturial都没有读完，竟然使用一堆if来过滤抓到的数据包，怪不得之前内网传文件达10M速度的时候，客户端占的CPU狂飙了。为捕捉过程设置了驱动级别的过滤器，使用回呼方式抓包，对一些函数流程进行重构，最后这个版本运行的时候占内存不到10M，CPU占用率也低多了。 这两天对着一个libpcap的抓包示例，一步步地将包分析的功能改了出来，然后就是手动创建的报文，其中一个小插曲是用到的MD5算法，在Java中有个内建的digest功能，但C语言哪来这东西，上网找，连续下了几个版本，测试一下，有些算出来的值是错的，有些每次算出来都不一样，气死我了，看来是因为我现在用的是amd64版本的系统，算法里面的数据类型不兼容所致。最后在MD5 Homepage (unofficial)找到了L. Peter Deutsch's的版本才正常。 对着wireshark满是16进制数的窗口用笔划了两天框框彻底搞清楚了协议包的结构，然后在gvim里面倒腾了代码，终于程序完成了。不知为什么，写这个程序有很亢奋的感觉，昨天晚上是搞到3点钟才睡，然后早上7点多就爬了起来继续coding，不是我不想睡，而是有问题晾在那里没解决就睡觉的话，就只会整晚失眠了。逃了一天课，终于大功告成，本来还想实现配置文件的功能，不过想想还是算了，很容易就能用脚本来记录。]]></description>
			<content:encoded><![CDATA[<p>一直以来在Linux下要接入神州数码认证用的是<a href="http://www.yaoqi.name/">姚琦</a>开发的Java版认证工具，不过现在起，使用神码的同学可以把jvm抛弃啦！PT开发出了C语言版的神州数码802.1x客户端！</p>
<p><img style="max-width: 800px; width: 293px; height: 237px;" src="http://apt-blog.net/wp-content/uploads/2009/05/zdcclient.png" /></p>
<p>项目主页：<a target="_blank" href="http://code.google.com/p/zdcclient/">http://code.google.com/p/zdcclient/</a></p>
<p>
<h3>开发手记</h3>
<p>PT的客户端版本虽然是命令行的版本，但是功能和<a href="http://www.yaoqi.name/">姚琦</a>的Java版功能没多大差别，目前支持自定义接入网卡、支持DHCP、支持程序运行后自动fork到后台，用户名等通过参数传入程序。</p>
<p>Java版的软件虽然一般使用起来没太大区别，但是当系统中没有jvm虚拟机和软件依赖的库，而且电脑又不能上网的时候，这可是相当棘手的问题，我去年就为此在<a target="_blank" href="http://wiki.ubuntu.org.cn/%E7%A5%9E%E5%B7%9E%E6%95%B0%E7%A0%81802.1x%E3%80%81DCBA%E5%8D%8F%E8%AE%AE%E8%AE%A4%E8%AF%81%E6%96%B9%E6%A1%88">Ubuntu-cn的Wiki写了一篇教程</a>，如何从源里面抓jvm的一堆包回来安装，再折腾一番才能用。况且Java程序占的资源颇大，就那个0.6.1版的客户端，常驻内存有50M！</p>
<p><a href="http://www.yaoqi.name/">姚琦</a>的个人网站上面公布了他的客户端软件的源码，之前有下载回来，不过一直没看，早天兴起把文件重新放到Netbeans里面来编译一次，发现能编译却不能认证！好奇之下跟踪了其代码，把带界面的1500多行的程序删减到只剩400行的命令行程序，然后再根据抓数据包的对比，发现是这个版本获取本机地址的代码有问题，在Linux下获取本机IP是错的，这样组成的数据包去认证，当然不行了，具体在<a target="_blank" href="http://blog.linuxeden.com/?uid-51058-action-viewspace-itemid-4713">这里</a>有人解释。</p>
<p>摸清楚认证过程的来龙去脉后，就打算自己用C来写一个客户端，虽然我有2G内存，但老被占着几十M也不舒服。Java里面用的jpcap，是Java用JNI对libpcap的封装，之前我弄过编译amd64版时候接触过，发现其功能很强大，使用也不复杂，于是对写个原生C语言版的客户端也有了信心。</p>
<p>为了弄清整个程序的工作流程，我进一步优化了Java版的代码，400多行最后剩下200多了，姚学长的编码好像有点太过那个，呃……而且姚学长好像连jpcap的toturial都没有读完，竟然使用一堆if来过滤抓到的数据包，怪不得之前内网传文件达10M速度的时候，客户端占的CPU狂飙了。为捕捉过程设置了驱动级别的过滤器，使用回呼方式抓包，对一些函数流程进行重构，最后这个版本运行的时候占内存不到10M，CPU占用率也低多了。</p>
<p>这两天对着一个libpcap的抓包示例，一步步地将包分析的功能改了出来，然后就是手动创建的报文，其中一个小插曲是用到的MD5算法，在Java中有个内建的digest功能，但C语言哪来这东西，上网找，连续下了几个版本，测试一下，有些算出来的值是错的，有些每次算出来都不一样，气死我了，看来是因为我现在用的是amd64版本的系统，算法里面的数据类型不兼容所致。最后在<a target="_blank" href="http://userpages.umbc.edu/%7Emabzug1/cs/md5/md5.html">MD5 Homepage (unofficial)</a>找到了L. Peter Deutsch's的版本才正常。</p>
<p>对着wireshark满是16进制数的窗口用笔划了两天框框彻底搞清楚了协议包的结构，然后在gvim里面倒腾了代码，终于程序完成了。不知为什么，写这个程序有很亢奋的感觉，昨天晚上是搞到3点钟才睡，然后早上7点多就爬了起来继续coding，不是我不想睡，而是有问题晾在那里没解决就睡觉的话，就只会整晚失眠了。逃了一天课，终于大功告成，本来还想实现配置文件的功能，不过想想还是算了，很容易就能用脚本来记录。</p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/digital_china_802-1x_client/feed</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss>
