blob: 353291f716803317b243a3cbae371c513a3c1b80 [file] [log] [blame]
A R Karthick05d9b5f2016-06-08 11:53:54 -07001#
Chetan Gaonkercfcce782016-05-10 10:10:42 -07002# Copyright 2016-present Ciena Corporation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
A R Karthick05d9b5f2016-06-08 11:53:54 -07007#
Chetan Gaonkercfcce782016-05-10 10:10:42 -07008# http://www.apache.org/licenses/LICENSE-2.0
A R Karthick05d9b5f2016-06-08 11:53:54 -07009#
Chetan Gaonkercfcce782016-05-10 10:10:42 -070010# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
A R Karthicka2e53d62016-02-19 17:38:30 -080016#### Authentication parameters
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080017from scapy.all import *
A R Karthickaa10a202016-08-15 15:06:21 -070018from scapy_ssl_tls.ssl_tls import *
A R Karthicka2e53d62016-02-19 17:38:30 -080019from socket import *
20from struct import *
A R Karthicka2e53d62016-02-19 17:38:30 -080021import sys
A R Karthick8f930292017-07-07 12:36:22 -070022import binascii
A R Karthicka2e53d62016-02-19 17:38:30 -080023from nose.tools import assert_equal, assert_not_equal, assert_raises, assert_true
A R Karthick76a497a2017-04-12 10:59:39 -070024from CordTestUtils import log_test
A R Karthicka2e53d62016-02-19 17:38:30 -080025
26USER = "raduser"
27PASS = "radpass"
28WRONG_USER = "XXXX"
29WRONG_PASS = "XXXX"
30NO_USER = ""
31NO_PASS = ""
32DEV = "tap0"
33ETHERTYPE_PAE = 0x888e
34PAE_GROUP_ADDR = "\xff\xff\xff\xff\xff\xff"
35EAPOL_VERSION = 1
36EAPOL_EAPPACKET = 0
37EAPOL_START = 1
38EAPOL_LOGOFF = 2
39EAPOL_KEY = 3
40EAPOL_ASF = 4
41EAP_REQUEST = 1
42EAP_RESPONSE = 2
43EAP_SUCCESS = 3
44EAP_FAILURE = 4
45EAP_TYPE_ID = 1
46EAP_TYPE_MD5 = 4
47EAP_TYPE_MSCHAP = 26
48EAP_TYPE_TLS = 13
49cCertMsg = '\x0b\x00\x00\x03\x00\x00\x00'
50TLS_LENGTH_INCLUDED = 0x80
A R Karthickaa10a202016-08-15 15:06:21 -070051TLS_MORE_FRAGMENTS = 0x40
A R Karthicka2e53d62016-02-19 17:38:30 -080052
A R Karthicka2e53d62016-02-19 17:38:30 -080053class EapolPacket(object):
A R Karthick05d9b5f2016-06-08 11:53:54 -070054
ChetanGaonker6138fcd2016-08-18 17:56:39 -070055 src_mac_map = { 'bcast': 'ff:ff:ff:ff:ff:ff',
56 'mcast': '01:80:C2:00:00:03',
57 'zeros': '00:00:00:00:00:00',
58 'default': None
59 }
60
A R Karthicka2e53d62016-02-19 17:38:30 -080061 def __init__(self, intf = 'veth0'):
62 self.intf = intf
63 self.s = None
A R Karthickaa10a202016-08-15 15:06:21 -070064 self.max_recv_size = 1600
A R Karthicka2e53d62016-02-19 17:38:30 -080065
ChetanGaonker6138fcd2016-08-18 17:56:39 -070066 def setup(self, src_mac = 'default'):
A R Karthicka2e53d62016-02-19 17:38:30 -080067 self.s = socket(AF_PACKET, SOCK_RAW, htons(ETHERTYPE_PAE))
68 self.s.bind((self.intf, ETHERTYPE_PAE))
69 self.mymac = self.s.getsockname()[4]
ChetanGaonker6138fcd2016-08-18 17:56:39 -070070 mac = None
A R Karthick8f930292017-07-07 12:36:22 -070071 mac_str = None
72 if src_mac == 'random':
73 mac = RandMAC()._fix()
74 elif src_mac in self.src_mac_map:
ChetanGaonker6138fcd2016-08-18 17:56:39 -070075 mac = self.src_mac_map[src_mac]
76 if mac is None:
77 mac = self.mymac
A R Karthick8f930292017-07-07 12:36:22 -070078 mac_str = binascii.hexlify(mac)
79 if mac_str is None:
80 mac_str = mac
ChetanGaonker6138fcd2016-08-18 17:56:39 -070081 self.llheader = Ether(dst = PAE_GROUP_ADDR, src = mac, type = ETHERTYPE_PAE)
A R Karthick76a497a2017-04-12 10:59:39 -070082 log_test.info('llheader packet is %s'%self.llheader.show())
A R Karthick8f930292017-07-07 12:36:22 -070083 log_test.info('source mac of packet is %s'%mac_str)
Chetan Gaonker5b366302016-03-21 16:18:21 -070084 self.recv_sock = L2Socket(iface = self.intf, type = ETHERTYPE_PAE)
A R Karthicka2e53d62016-02-19 17:38:30 -080085
86 def cleanup(self):
87 if self.s is not None:
88 self.s.close()
89 self.s = None
A R Karthick05d9b5f2016-06-08 11:53:54 -070090
A R Karthicka2e53d62016-02-19 17:38:30 -080091 def eapol(self, req_type, payload=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080092 return EAPOL(version = EAPOL_VERSION, type = req_type)/payload
A R Karthicka2e53d62016-02-19 17:38:30 -080093
94 def eap(self, code, pkt_id, req_type=0, data=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080095 return EAP(code = code, id = pkt_id, type = req_type)/data
A R Karthicka2e53d62016-02-19 17:38:30 -080096
A R Karthickaa10a202016-08-15 15:06:21 -070097 def eapFragmentSend(self, code, pkt_id, flags = TLS_LENGTH_INCLUDED, payload = "", fragsize = 1024):
98 req_type = EAP_TYPE_TLS
99 if code in [ EAP_SUCCESS, EAP_FAILURE ]:
100 data = pack("!BBH", code, pkt_id, 4)
101 self.eapol_send(EAPOL_EAPPACKET, data)
102 return True
103
104 if len(payload) <= fragsize:
105 if flags & TLS_LENGTH_INCLUDED:
106 flags_dlen = pack("!BL", flags, len(payload))
107 data = pack("!BBHB", code, pkt_id, 5 + len(flags_dlen) + len(payload), req_type) \
108 + flags_dlen + payload
109 self.eapol_send(EAPOL_EAPPACKET, data)
110 return True
111 flags_str = pack("!B", flags)
112 data = pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(payload), req_type) + flags_str + payload
113 self.eapol_send(EAPOL_EAPPACKET, data)
114 return True
115
116 fragments = []
117 data = payload[:]
118 frag = 0
119 def eapol_frag_cb(pkt):
120 r = str(pkt)
121 tls_data = r[self.TLS_OFFSET:]
122 frag_data = fragments[frag]
123 ##change packet id in response to match request
124 eap_payload = frag_data[:1] + pack("!B", pkt[EAP].id) + frag_data[2:]
125 self.eapol_send(EAPOL_EAPPACKET, eap_payload)
126
127 while len(data) > 0:
128 data_frag = data[:fragsize]
129 data = data[fragsize:]
130 if frag == 0:
131 ##first frag, include the total length
132 flags_dlen = pack("!BL", TLS_LENGTH_INCLUDED | TLS_MORE_FRAGMENTS, len(payload))
133 fragments.append(pack("!BBHB", code, pkt_id, 5 + len(flags_dlen) + len(data_frag), req_type) \
134 + flags_dlen + data_frag)
135 else:
136 if len(data) > 0:
137 flags = TLS_MORE_FRAGMENTS
138 else:
139 flags = 0
140 flags_str = pack("!B", flags)
141 fragments.append(pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data_frag), req_type) + \
142 flags_str + data_frag)
143 frag += 1
144
145 frag = 0
146 self.eapol_send(EAPOL_EAPPACKET, fragments[frag])
147 for frag in range(len(fragments)-1):
148 frag += 1
149 r = self.eapol_scapy_recv(cb = eapol_frag_cb,
150 lfilter = lambda pkt: EAP in pkt and pkt[EAP].type == EAP_TYPE_TLS and \
151 pkt[EAP].code == EAP.REQUEST)
152
153 return True
154
A R Karthicka2e53d62016-02-19 17:38:30 -0800155 def eapTLS(self, code, pkt_id, flags = TLS_LENGTH_INCLUDED, data=""):
156 req_type = EAP_TYPE_TLS
157 if code in [EAP_SUCCESS, EAP_FAILURE]:
158 return pack("!BBH", code, pkt_id, 4)
159 else:
160 if flags & TLS_LENGTH_INCLUDED:
161 flags_dlen = pack("!BL", flags, len(data))
162 return pack("!BBHB", code, pkt_id, 5+len(flags_dlen)+len(data), req_type) + flags_dlen + data
163 flags_str = pack("!B", flags)
164 return pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data), req_type) + flags_str + data
165
A R Karthickaa10a202016-08-15 15:06:21 -0700166 def eapTLSFragment(self, code, pkt_id, frag, data="", data_len = 0):
167 req_type = EAP_TYPE_TLS
168 if frag == 0:
169 flags = TLS_LENGTH_INCLUDED | TLS_MORE_FRAGMENTS
170 elif frag > 0:
171 flags = TLS_MORE_FRAGMENTS
172 else:
173 #last fragment
174 flags = 0
175 if data_len == 0:
176 data_len = len(data)
177 if flags & TLS_LENGTH_INCLUDED:
178 flags_dlen = pack("!BL", flags, data_len)
179 return pack("!BBHB", code, pkt_id, 5+len(flags_dlen)+len(data), req_type) + flags_dlen + data
180 flags_str = pack("!B", flags)
181 return pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data), req_type) + flags_str + data
182
A R Karthicka2e53d62016-02-19 17:38:30 -0800183 def eapol_send(self, eapol_type, eap_payload):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -0800184 return sendp(self.llheader/self.eapol(eapol_type, eap_payload), iface=self.intf)
A R Karthicka2e53d62016-02-19 17:38:30 -0800185
186 def eapol_recv(self):
A R Karthickaa10a202016-08-15 15:06:21 -0700187 p = self.s.recv(self.max_recv_size)[14:]
A R Karthicka2e53d62016-02-19 17:38:30 -0800188 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
189 print "Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
190 assert_equal(pkt_type, EAPOL_EAPPACKET)
191 return p[4:]
192
A.R Karthickaa859b22017-06-12 14:50:35 -0700193 def eapol_scapy_recv(self, cb = None, lfilter = None, count = 1, timeout = 10):
Chetan Gaonker5b366302016-03-21 16:18:21 -0700194 def eapol_default_cb(pkt): pass
195 if cb is None:
196 cb = eapol_default_cb
A R Karthick05d9b5f2016-06-08 11:53:54 -0700197 return sniff(prn = cb, lfilter = lfilter, count = count, timeout = timeout, opened_socket = self.recv_sock)
Chetan Gaonker5b366302016-03-21 16:18:21 -0700198
A R Karthicka2e53d62016-02-19 17:38:30 -0800199 def eapol_start(self):
200 eap_payload = self.eap(EAPOL_START, 2)
201 return self.eapol_send(EAPOL_START, eap_payload)
202
A R Karthick307483c2016-06-06 17:05:19 -0700203 def eapol_logoff(self):
204 eap_payload = self.eap(EAPOL_LOGOFF, 2)
205 return self.eapol_send(EAPOL_LOGOFF, eap_payload)
206
A R Karthicka2e53d62016-02-19 17:38:30 -0800207 def eapol_id_req(self, pkt_id = 0, user = USER):
208 eap_payload = self.eap(EAP_RESPONSE, pkt_id, EAP_TYPE_ID, user)
209 return self.eapol_send(EAPOL_EAPPACKET, eap_payload)
210
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800211 def eap_md5_challenge_recv(self,rad_pwd):
212 PASS = rad_pwd
213 print 'Inside EAP MD5 Challenge Exchange'
A R Karthickaa10a202016-08-15 15:06:21 -0700214 p = self.s.recv(self.max_recv_size)[14:]
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800215 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
216 print "EAPOL Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
217 code, pkt_id, eaplen = unpack("!BBH", p[4:8])
218 print "EAP Code %d, id %d, len %d" %(code, pkt_id, eaplen)
219 assert_equal(code, EAP_REQUEST)
220 reqtype = unpack("!B", p[8:9])[0]
221 reqdata = p[9:4+eaplen]
222 print 'Request type is %d' %(reqtype)
223 assert_equal(reqtype, EAP_TYPE_MD5)
224 challenge=pack("!B",pkt_id)+PASS+reqdata[1:]
225 print "Generating md5 challenge for %s" % challenge
226 return (challenge,pkt_id)
227
228 def eap_Status(self):
229 print 'Inside EAP Status'
A R Karthickaa10a202016-08-15 15:06:21 -0700230 p = self.s.recv(self.max_recv_size)[14:]
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800231 code, id, eaplen = unpack("!BBH", p[4:8])
232 return code
233
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000234 @classmethod
235 def eap_invalid_tls_packets_info(self, invalid_field_name = None, invalid_field_value = None):
A R Karthick76a497a2017-04-12 10:59:39 -0700236 log_test.info( 'Changing invalid field values in tls auth packets' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000237 if invalid_field_name == 'eapolTlsVersion':
238 global EAPOL_VERSION
A R Karthick76a497a2017-04-12 10:59:39 -0700239 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000240 EAPOL_VERSION = invalid_field_value
241 if invalid_field_name == 'eapolTlsType':
242 global EAP_TYPE_TLS
A R Karthick76a497a2017-04-12 10:59:39 -0700243 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000244 EAP_TYPE_TLS = invalid_field_value
245 if invalid_field_name == 'eapolTypeID':
246 global EAP_TYPE_ID
A R Karthick76a497a2017-04-12 10:59:39 -0700247 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000248 EAP_TYPE_ID = invalid_field_value
249 if invalid_field_name == 'eapolResponse':
250 global EAP_RESPONSE
A R Karthick76a497a2017-04-12 10:59:39 -0700251 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000252 EAP_RESPONSE = invalid_field_value
253
254
255 @classmethod
256 def eap_tls_packets_field_value_replace(self, invalid_field_name = None):
A R Karthick76a497a2017-04-12 10:59:39 -0700257 log_test.info( 'Changing invalid field values in tls auth packets' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000258 if invalid_field_name == 'eapolTlsVersion':
259 global EAPOL_VERSION
260 EAPOL_VERSION = 1
A R Karthick76a497a2017-04-12 10:59:39 -0700261 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000262 if invalid_field_name == 'eapolTlsType':
263 global EAP_TYPE_TLS
264 EAP_TYPE_TLS = 13
A R Karthick76a497a2017-04-12 10:59:39 -0700265 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000266 if invalid_field_name == 'eapolTypeID':
267 global EAP_TYPE_ID
268 EAP_TYPE_ID = 1
A R Karthick76a497a2017-04-12 10:59:39 -0700269 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000270 if invalid_field_name == 'eapolResponse':
271 global EAP_RESPONSE
272 EAP_RESPONSE = 2
A R Karthick76a497a2017-04-12 10:59:39 -0700273 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )