<?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   无证程序员的PT桑 &#187; 认证协议</title>
	<atom:link href="http://apt-blog.net/tag/%e8%ae%a4%e8%af%81%e5%8d%8f%e8%ae%ae/feed" rel="self" type="application/rss+xml" />
	<link>http://apt-blog.net</link>
	<description>潜逃中。</description>
	<lastBuildDate>Fri, 18 May 2012 11:25:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>深入了解校园网802.1x认证的EAP协议(3)——联想802.1x认证细节</title>
		<link>http://apt-blog.net/details_about_802_1x_in_campus_authentication_3</link>
		<comments>http://apt-blog.net/details_about_802_1x_in_campus_authentication_3#comments</comments>
		<pubDate>Mon, 24 Aug 2009 12:12:28 +0000</pubDate>
		<dc:creator>BOYPT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAP]]></category>
		<category><![CDATA[联想]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/?p=526</guid>
		<description><![CDATA[联想的认证协议是我写的这几个802.1x实现里面相对简单的版本，没有太多古古怪怪的信息头信息尾部。 我们学校并没有使用过联想协议的认证系统，而是受了一位网友的邀请才写的，所以我连联想官方客户端的样子都没看到过，一直是由那网友抓包后发送过来，而我猜测地将其套入到此前我写的神州数码的认证程序里面，经过几天的调试，确实能用，虽然并不完全了解认证报文的每个细节。 PT实现的联想Linux客户端项目主页：http://code.google.com/p/zlevoclient/ 以下的说明是基于EAP协议过程的补充描述，如果不清楚EAP，可先读深入了解校园网802.1x认证的EAP协议(1)——EAP的总体流程。 认证过程报文的细节描述： EAPOL-Start、EAPOL-Logoff设置长度为0的协议包头，然后紧接6个意义不明的字节（可能是版本号之类），直接复制即可：&#160;{0x00, 0x00, 0x2f, 0xfc, 0x03, 0x00}; EAP-RESPONSE-Identity长度为5（头部） + username_length，无特别，跟EAP标准一致， EAP-RESPONSE-MD5_Challenge长度为6（头部） + 16（MD5值） + username_length，在MD5值之后，先紧接用户名，然后是4字节的本机IP地址，以及9个意义不明的字节，直接复制：{0x00, 0x00, 0x2f, 0xfc, 0x00, 0x03, 0x01, 0x01, 0x00}; EAPOL-KEEP-ALIVE当认证成功后，需要每60秒发送一次该报文，否则会断线；该报文的b:EAPOL 报文类型为0xFC，帧长值为12，其携带信息的前8字节在实际中似乎是随机变化，找不出其规律，不过实际上全部设0也可；后4字节则是本机IP。 在部分版本中，如吉林大学珠海学院，每隔5分钟（可能就在第五个EAPOL-KEEP-ALIVE发出之后）服务器会重新发来EAP-REQUEST-Identity，程序需要正确应答，特别要设置各个应答报文中的e:EAP通信id。 关于服务器返回的数据包，Success和Failure通常包含有中文编码的信息，标志是，EAP报文结束后，紧接0x00002ffc（大概0x18、0x19），其后接着是一个字节的报文长度，再后就是gb2312编码的中文信息。 由于协助我测试的湖南人文科技学院的网友他们的系统是纯手工设置网卡IP的，所以我也不清楚是否有像其他品牌的协议那样有动态静态IP位之类的信息位，如果发现这个版本的程序不能通过认证，可以自己抓包分析，或邮件联系PT。]]></description>
			<content:encoded><![CDATA[<p>联想的认证协议是我写的这几个802.1x实现里面相对简单的版本，没有太多古古怪怪的信息头信息尾部。</p>
<p>我们学校并没有使用过联想协议的认证系统，而是受了一位网友的邀请才写的，所以我连联想官方客户端的样子都没看到过，一直是由那网友抓包后发送过来，而我猜测地将其套入到此前我写的神州数码的认证程序里面，经过几天的调试，确实能用，虽然并不完全了解认证报文的每个细节。</p>
<p>PT实现的联想Linux客户端项目主页：<a target="_blank" href="http://code.google.com/p/zlevoclient/">http://code.google.com/p/zlevoclient/</a></p>
<p>以下的说明是基于EAP协议过程的补充描述，如果不清楚EAP，可先读<a href="http://apt-blog.net/archives/423.html">深入了解校园网802.1x认证的EAP协议(1)——EAP的总体流程</a>。</p>
<p>认证过程报文的细节描述：
<ol>
<li>EAPOL-Start、EAPOL-Logoff<br />设置长度为0的协议包头，然后紧接6个意义不明的字节（可能是版本号之类），直接复制即可：<br />&nbsp;{0x00, 0x00, 0x2f, 0xfc, 0x03, 0x00};</li>
<li>EAP-RESPONSE-Identity<br />长度为5（头部） + username_length，无特别，跟EAP标准一致，</li>
<li>EAP-RESPONSE-MD5_Challenge<br />长度为6（头部） + 16（MD5值） + username_length，在MD5值之后，先紧接用户名，然后是4字节的本机IP地址，以及9个意义不明的字节，直接复制：{0x00, 0x00, 0x2f, 0xfc, 0x00, 0x03, 0x01, 0x01, 0x00};</li>
<li>EAPOL-KEEP-ALIVE<br />当认证成功后，需要每60秒发送一次该报文，否则会断线；<br />该报文的<span style="font-family: monospace;">b:EAPOL 报文类型</span>为0xFC，帧长值为12，其携带信息的前8字节在实际中似乎是随机变化，找不出其规律，不过实际上全部设0也可；后4字节则是本机IP。</li>
</ol>
<p>在部分版本中，如吉林大学珠海学院，每隔5分钟（可能就在第五个EAPOL-KEEP-ALIVE发出之后）服务器会重新发来<span style="font-family: monospace;">EAP-REQUEST-Identity</span>，程序需要正确应答，特别要设置各个应答报文中的e:EAP通信id。</p>
<p>关于服务器返回的数据包，Success和Failure通常包含有中文编码的信息，标志是，EAP报文结束后，紧接0x00002ffc（大概0x18、0x19），其后接着是一个字节的报文长度，再后就是gb2312编码的中文信息。</p>
<p>由于协助我测试的<a name="通过测试的环境">湖南人文科技学院的网友他们的系统是纯手工设置网卡IP的，所以我也不清楚是否有像其他品牌的协议那样有动态静态IP位之类的信息位，如果发现这个版本的程序不能通过认证，可以自己抓包分析，或邮件联系PT。</a></p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/details_about_802_1x_in_campus_authentication_3/feed</wfw:commentRss>
		<slash:comments>8</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>3</slash:comments>
		</item>
		<item>
		<title>深入了解校园网802.1x认证的EAP协议(1)——EAP的总体流程</title>
		<link>http://apt-blog.net/details_about_802_1x_in_campus_authentication_1</link>
		<comments>http://apt-blog.net/details_about_802_1x_in_campus_authentication_1#comments</comments>
		<pubDate>Tue, 09 Jun 2009 12:16:54 +0000</pubDate>
		<dc:creator>PT</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[802.1x]]></category>
		<category><![CDATA[EAP]]></category>
		<category><![CDATA[认证协议]]></category>
		<guid isPermaLink="false">http://apt-blog.net/archives/423.html</guid>
		<description><![CDATA[EAP（Extensible Authentication Protocol），是一个普遍使用的认证机制，详细介绍可见Wikipedia。本文介绍的，是被广泛使用在国内高校校园网的认证机制使用的EAP协议，暂不具体地说明某个品牌的私有协议如何如何，而是从整体角度看EAP协议如何工作，从一个第三方Supplicant客户端的开发者角度解释EAP的通信机制。在后续的章节将继续介绍PT接触过的几种认证协议中，国内的“标准践踏者们”如何实现各种变态的认证协议。 文中出现的术语和名词，基本参考了RFC 3748的相关描述，以及Wireshark软件对相关报文的解释用词。 认证过程简述： 主机向服务器（多播或广播地址）发送EAPOL-Start 服务器向主机发送EAP-REQUEST-Identity要求验证身份的请求 主机向服务器发送EAP-RESPONSE-Identity回应 服务器向主机发送EAP-REQUEST-MD5_Challenge要求验证密码的MD5校验值 主机向服务器发送EAP-RESPONSE-MD5_Challenge回应 服务器向主机发送EAP-Success 保持连接的通信... 当然这只是一般过程，如果在任何时候服务器发来EAP-Failure数据包，都表示整个认证过程终止。&#160;Supplicant主机&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 服务器 &#160;-----------&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; -------------&#160;&#160;&#160; &#124;------------------------------&#62;&#124;&#160;&#160;&#160; &#124; 1.&#160; EAPOL-Start&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;&#60;------------------------------&#124;&#160;&#160;&#160; &#124; 2. EAP-REQUEST-Identity&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;------------------------------&#62;&#124;&#160;&#160;&#160; &#124; 3. EAP-RESPONSE-Identity&#160;&#160;&#160;&#160;&#160; &#124; &#160;&#160;&#160; &#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;&#60;------------------------------&#124;&#160;&#160;&#160; &#124; 4. EAP-REQUEST-MD5_Challenge&#160; &#124; &#160;&#160;&#160; &#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;------------------------------&#62;&#124;&#160;&#160;&#160; &#124; 5. EAP-RESPONSE-MD5_Challenge &#124;&#160;&#160;&#160; &#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#124;&#160;&#160;&#160; &#124;&#60;------------------------------&#124;&#160;&#160;&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>EAP（Extensible Authentication Protocol），是一个普遍使用的认证机制，详细介绍可见<a target="_blank" href="http://zh.wikipedia.org/wiki/EAP">Wikipedia</a>。本文介绍的，是被广泛使用在国内高校校园网的认证机制使用的EAP协议，暂不具体地说明某个品牌的私有协议如何如何，而是从整体角度看EAP协议如何工作，从一个第三方Supplicant客户端的开发者角度解释EAP的通信机制。在后续的章节将继续介绍PT接触过的几种认证协议中，国内的“<span style="text-decoration: underline;">标准践踏者们</span>”如何实现各种变态的认证协议。</p>
<p>文中出现的术语和名词，基本参考了<a href="http://tools.ietf.org/html/rfc3748" class="external" title="http://tools.ietf.org/html/rfc3748">RFC 3748</a>的相关描述，以及Wireshark软件对相关报文的解释用词。</p>
<p>认证过程简述：
<ol>
<li>主机向服务器（多播或广播地址）发送EAPOL-Start</li>
<li>服务器向主机发送EAP-REQUEST-Identity要求验证身份的请求</li>
<li>主机向服务器发送EAP-RESPONSE-Identity回应</li>
<li>服务器向主机发送EAP-REQUEST-MD5_Challenge要求验证密码的MD5校验值</li>
<li>主机向服务器发送EAP-RESPONSE-MD5_Challenge回应</li>
<li>服务器向主机发送EAP-Success</li>
<li>保持连接的通信...</li>
</ol>
<p>当然这只是一般过程，如果在任何时候服务器发来EAP-Failure数据包，都表示整个认证过程终止。<br /><span style="font-family: monospace;"><br />&nbsp;Supplicant主机&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务器 <br />&nbsp;-----------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------------<br />&nbsp;&nbsp;&nbsp; |------------------------------&gt;|<br />&nbsp;&nbsp;&nbsp; | 1.&nbsp; EAPOL-Start&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&lt;------------------------------|<br />&nbsp;&nbsp;&nbsp; | 2. EAP-REQUEST-Identity&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |------------------------------&gt;|<br />&nbsp;&nbsp;&nbsp; | 3. EAP-RESPONSE-Identity&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&lt;------------------------------|<br />&nbsp;&nbsp;&nbsp; | 4. EAP-REQUEST-MD5_Challenge&nbsp; | <br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |------------------------------&gt;|<br />&nbsp;&nbsp;&nbsp; | 5. EAP-RESPONSE-MD5_Challenge |<br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&lt;------------------------------|<br />&nbsp;&nbsp;&nbsp; | 6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAP-Success&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br /></span><br />在以太网中，EAP协议当然也是通过以太网帧的格式来传送，帧类型为0x888e，在基于pcap的抓包程序中，可使用"ether proto 0x888e"来抓取。<br /><span style="font-family: monospace;"><br />Ethernet-Header：<br />################################################<br />#&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13&nbsp; #<br /># +----------------+----------------+--------+ #<br /># |DST--MAC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |SRC--MAC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |0x888e&nbsp; | #<br /># +----------------+----------------+--------+ #<br />################################################<br /></span><br />
<br />
当用作802.1x应答帧时，常使用802.1x分配的多播地址01-80-c2-00-00-03作为目的地址。<br />
<br />从Wiki的简介得知，EAP协议不仅可用于本文关注的以太网环境中，还可在无线WLAN、令牌环网中应用，而这些链路帧是各不相同的，这就是为什么有EAPOL类型的数据帧，用以抽象EAP协议报文。<br /><span style="font-family: monospace;"><br />EAPOL-报文结构<br />############################################<br />#&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14 15 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># | Ethernet-Header&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |a|b|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br />#&nbsp;&nbsp;&nbsp; 17 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># |c&nbsp; |Packet Body&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br />############################################<br />a:EAPOL 协议版本<br />b:EAPOL 报文类型<br />c:EAPOL 帧长度</p>
<p>a类型说明：通常为常量0x01</p>
<p>b类型取值：<br />EAPOL-Packet :&nbsp;&nbsp; 0x00<br />EAPOL-Start:&nbsp;&nbsp;&nbsp;&nbsp; 0x01<br />EAPOL-Logoff:&nbsp;&nbsp;&nbsp; 0x02<br /></span><br />各种EAP协议的信息交互，封装在EAPOL-Packet类型的EAPOL报文内。至于EAP报文的格式，基本就是如下所示。<br /><span style="font-family: monospace;"><br />EAP-报文结构<br />#########################################<br />#&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15 &nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&nbsp;&nbsp;&nbsp;&nbsp; #<br /># |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&nbsp;&nbsp;&nbsp;&nbsp; #<br />#&nbsp;&nbsp; 17 18 19 21 22 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+--------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># |&nbsp;&nbsp; |d|e|f&nbsp; |g|EAP Body&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br /># +-+-+-+-+-+-+-+--------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #<br />#########################################</p>
<p>d:EAP通信类型<br />e:EAP通信id<br />f:EAP数据长度 <br />g:EAP协商类型</p>
<p>d类型取值：<br />EAP-Request:&nbsp; 0x01<br />EAP-Resopnse: 0x02<br />EAP-Success:&nbsp; 0x03<br />EAP-Failure:&nbsp; 0x04</p>
<p>e类型说明：<br />通常由服务器发来的报文指定，在连续的报文内使用这个id来协商或者计算MD5值的数据之一。</p>
<p>g类型取值：<br />Identity:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x01<br />MD5_Challenge:&nbsp;&nbsp; 0x04<br /></span><br />一个EAP Supplicant客户端程序主要的任务就是处理服务器发来的数据帧和组织回应服务器的数据帧。除了根据上述的“c:EAP通信类型”和“f:EAP协商类型”位来识别协商类型外，更需要根据这些报文内的其他数据来组织回应数据帧。</p>
<p>下面是需要程序构建的数据包的大概细节：</p>
<p>（需要注意EAPOL帧和EAP帧的两处长度位置，前者的长度是不算EAPOL头的4个字节的，而后者则包含自身头部的5个字节，所以这两个长度的值可能是一致的，但具体可能有扩展信息放在EAPOL帧尾部，则前者比后者大。）</p>
<p><span style="font-weight: bold;">1.EAPOL-Start、EAPOL-Logoff</span><br />通常是比较简单的数据包，只需填好相应的位，没有其他附加消息，EAPOL-Start、EAPOL-Logoff两种报文长度为0，通常建立起来两个报文的长度就只有18字节。<br /><span style="font-family: monospace;"></span><br /><span style="font-weight: bold;">2.EAP-REQUEST-Identity</span><br />服务器发来的这个报文也比较简单，可能唯一有用的数据是“e:EAP通信id”位，需要给发送回去的报文中把相应位设置为该值，虽然这很可能是常数。<br /><span style="font-family: monospace;"><br />Identity格式<br />+-+-+-+-.....-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br />| EAP Header&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; Username<br />+-+-+-+-.....-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br /><span style="font-weight: bold;">3.EAP-RESPONSE-Identity</span><br />只需要设置“d:EAP通信id”位，然后在EAP头后紧接用户名的ASCII码信息。有些品牌的协议中，则顺带在此数据包开始校验客户端的IP、版本号等信息。<br /><span style="font-family: monospace;"></span><br /><span style="font-weight: bold;">4.EAP-REQUEST-MD5_Challenge</span><br />服务器请求MD5校验的报文中包含了重要的信息，首先也是“e:EAP通信id”位，后一个报文也需要设置该位；<br />在EAP报头后紧接一个一位的长度值L（常量0x10），表示紧跟其后的重要数据的长度，其后的16位值则需要用来计算下一个报文中的信息，我们称之为attach-key。<br /><span style="font-family: monospace;"><br />MD5_Challenge格式<br />+-+-+-+-.....-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br />| EAP Header&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |L|MD5-Key/Value<br />+-+-+-+-.....-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br /><span style="font-weight: bold;">5.EAP-RESPONSE-MD5_Challenge</span><br />首先需要设置“d:EAP通信id”位，然后构建一个这样的字节数组［(e:EAP通信id)(用户密码的ASCII)(attach-key)]，这个字节的长度当然是(1+用户密码长度+16)，然后送入MD5计算函数中，获得16位的计算结果，再把这16位计算结果填入报文。报文格式跟请求的类似，在包头后紧接一位长度值，当然是0x10，然后是16位的计算结果。</p>
<p>一个客户端程序所做的事情通常就是这么多，而因为EAP协议的“Extensible”的特性，几乎我们见到的每个品牌的协议都有所扩展，而且各不相同，所以各个品牌之间的客户端甚至交换机等设备都可能完全不可兼容的，其协议很可能在上述的报文中都添加一个信息尾，用来校验各种信息，具体的情况请留意PT博客的后续文章。<span style="font-family: 'sans-serif';"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://apt-blog.net/details_about_802_1x_in_campus_authentication_1/feed</wfw:commentRss>
		<slash:comments>13</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>43</slash:comments>
		</item>
	</channel>
</rss>

