blob: a3652c836dea8395a8625164e2771363d709bfb1 [file] [log] [blame]
Matteo Scandolo48d3d2d2017-08-08 13:05:27 -07001
2# Copyright 2017-present Open Networking Foundation
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
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# 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
16
A R Karthick05d9b5f2016-06-08 11:53:54 -070017#
Chetan Gaonkercfcce782016-05-10 10:10:42 -070018# Copyright 2016-present Ciena Corporation
19#
20# Licensed under the Apache License, Version 2.0 (the "License");
21# you may not use this file except in compliance with the License.
22# You may obtain a copy of the License at
A R Karthick05d9b5f2016-06-08 11:53:54 -070023#
Chetan Gaonkercfcce782016-05-10 10:10:42 -070024# http://www.apache.org/licenses/LICENSE-2.0
A R Karthick05d9b5f2016-06-08 11:53:54 -070025#
Chetan Gaonkercfcce782016-05-10 10:10:42 -070026# Unless required by applicable law or agreed to in writing, software
27# distributed under the License is distributed on an "AS IS" BASIS,
28# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29# See the License for the specific language governing permissions and
30# limitations under the License.
31#
A R Karthicka2e53d62016-02-19 17:38:30 -080032#### Authentication parameters
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080033from scapy.all import *
A R Karthickaa10a202016-08-15 15:06:21 -070034from scapy_ssl_tls.ssl_tls import *
A R Karthicka2e53d62016-02-19 17:38:30 -080035from socket import *
36from struct import *
A R Karthicka2e53d62016-02-19 17:38:30 -080037import sys
A R Karthick8f930292017-07-07 12:36:22 -070038import binascii
A R Karthicka2e53d62016-02-19 17:38:30 -080039from nose.tools import assert_equal, assert_not_equal, assert_raises, assert_true
A R Karthick76a497a2017-04-12 10:59:39 -070040from CordTestUtils import log_test
A R Karthicka2e53d62016-02-19 17:38:30 -080041
42USER = "raduser"
43PASS = "radpass"
44WRONG_USER = "XXXX"
45WRONG_PASS = "XXXX"
46NO_USER = ""
47NO_PASS = ""
48DEV = "tap0"
49ETHERTYPE_PAE = 0x888e
50PAE_GROUP_ADDR = "\xff\xff\xff\xff\xff\xff"
51EAPOL_VERSION = 1
52EAPOL_EAPPACKET = 0
53EAPOL_START = 1
54EAPOL_LOGOFF = 2
55EAPOL_KEY = 3
56EAPOL_ASF = 4
57EAP_REQUEST = 1
58EAP_RESPONSE = 2
59EAP_SUCCESS = 3
60EAP_FAILURE = 4
61EAP_TYPE_ID = 1
62EAP_TYPE_MD5 = 4
63EAP_TYPE_MSCHAP = 26
64EAP_TYPE_TLS = 13
65cCertMsg = '\x0b\x00\x00\x03\x00\x00\x00'
66TLS_LENGTH_INCLUDED = 0x80
A R Karthickaa10a202016-08-15 15:06:21 -070067TLS_MORE_FRAGMENTS = 0x40
A R Karthicka2e53d62016-02-19 17:38:30 -080068
A R Karthicka2e53d62016-02-19 17:38:30 -080069class EapolPacket(object):
A R Karthick05d9b5f2016-06-08 11:53:54 -070070
ChetanGaonker6138fcd2016-08-18 17:56:39 -070071 src_mac_map = { 'bcast': 'ff:ff:ff:ff:ff:ff',
72 'mcast': '01:80:C2:00:00:03',
73 'zeros': '00:00:00:00:00:00',
74 'default': None
75 }
76
A R Karthicka2e53d62016-02-19 17:38:30 -080077 def __init__(self, intf = 'veth0'):
78 self.intf = intf
79 self.s = None
A R Karthickaa10a202016-08-15 15:06:21 -070080 self.max_recv_size = 1600
A R Karthicka2e53d62016-02-19 17:38:30 -080081
ChetanGaonker6138fcd2016-08-18 17:56:39 -070082 def setup(self, src_mac = 'default'):
A R Karthicka2e53d62016-02-19 17:38:30 -080083 self.s = socket(AF_PACKET, SOCK_RAW, htons(ETHERTYPE_PAE))
84 self.s.bind((self.intf, ETHERTYPE_PAE))
85 self.mymac = self.s.getsockname()[4]
ChetanGaonker6138fcd2016-08-18 17:56:39 -070086 mac = None
A R Karthick8f930292017-07-07 12:36:22 -070087 mac_str = None
88 if src_mac == 'random':
89 mac = RandMAC()._fix()
90 elif src_mac in self.src_mac_map:
ChetanGaonker6138fcd2016-08-18 17:56:39 -070091 mac = self.src_mac_map[src_mac]
92 if mac is None:
93 mac = self.mymac
A R Karthick8f930292017-07-07 12:36:22 -070094 mac_str = binascii.hexlify(mac)
95 if mac_str is None:
96 mac_str = mac
ChetanGaonker6138fcd2016-08-18 17:56:39 -070097 self.llheader = Ether(dst = PAE_GROUP_ADDR, src = mac, type = ETHERTYPE_PAE)
A R Karthick76a497a2017-04-12 10:59:39 -070098 log_test.info('llheader packet is %s'%self.llheader.show())
A R Karthick8f930292017-07-07 12:36:22 -070099 log_test.info('source mac of packet is %s'%mac_str)
Chetan Gaonker5b366302016-03-21 16:18:21 -0700100 self.recv_sock = L2Socket(iface = self.intf, type = ETHERTYPE_PAE)
A R Karthicka2e53d62016-02-19 17:38:30 -0800101
102 def cleanup(self):
103 if self.s is not None:
104 self.s.close()
105 self.s = None
A R Karthick05d9b5f2016-06-08 11:53:54 -0700106
A R Karthicka2e53d62016-02-19 17:38:30 -0800107 def eapol(self, req_type, payload=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -0800108 return EAPOL(version = EAPOL_VERSION, type = req_type)/payload
A R Karthicka2e53d62016-02-19 17:38:30 -0800109
110 def eap(self, code, pkt_id, req_type=0, data=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -0800111 return EAP(code = code, id = pkt_id, type = req_type)/data
A R Karthicka2e53d62016-02-19 17:38:30 -0800112
A R Karthickaa10a202016-08-15 15:06:21 -0700113 def eapFragmentSend(self, code, pkt_id, flags = TLS_LENGTH_INCLUDED, payload = "", fragsize = 1024):
114 req_type = EAP_TYPE_TLS
115 if code in [ EAP_SUCCESS, EAP_FAILURE ]:
116 data = pack("!BBH", code, pkt_id, 4)
117 self.eapol_send(EAPOL_EAPPACKET, data)
118 return True
119
120 if len(payload) <= fragsize:
121 if flags & TLS_LENGTH_INCLUDED:
122 flags_dlen = pack("!BL", flags, len(payload))
123 data = pack("!BBHB", code, pkt_id, 5 + len(flags_dlen) + len(payload), req_type) \
124 + flags_dlen + payload
125 self.eapol_send(EAPOL_EAPPACKET, data)
126 return True
127 flags_str = pack("!B", flags)
128 data = pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(payload), req_type) + flags_str + payload
129 self.eapol_send(EAPOL_EAPPACKET, data)
130 return True
131
132 fragments = []
133 data = payload[:]
134 frag = 0
135 def eapol_frag_cb(pkt):
136 r = str(pkt)
137 tls_data = r[self.TLS_OFFSET:]
138 frag_data = fragments[frag]
139 ##change packet id in response to match request
140 eap_payload = frag_data[:1] + pack("!B", pkt[EAP].id) + frag_data[2:]
141 self.eapol_send(EAPOL_EAPPACKET, eap_payload)
142
143 while len(data) > 0:
144 data_frag = data[:fragsize]
145 data = data[fragsize:]
146 if frag == 0:
147 ##first frag, include the total length
148 flags_dlen = pack("!BL", TLS_LENGTH_INCLUDED | TLS_MORE_FRAGMENTS, len(payload))
149 fragments.append(pack("!BBHB", code, pkt_id, 5 + len(flags_dlen) + len(data_frag), req_type) \
150 + flags_dlen + data_frag)
151 else:
152 if len(data) > 0:
153 flags = TLS_MORE_FRAGMENTS
154 else:
155 flags = 0
156 flags_str = pack("!B", flags)
157 fragments.append(pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data_frag), req_type) + \
158 flags_str + data_frag)
159 frag += 1
160
161 frag = 0
162 self.eapol_send(EAPOL_EAPPACKET, fragments[frag])
163 for frag in range(len(fragments)-1):
164 frag += 1
165 r = self.eapol_scapy_recv(cb = eapol_frag_cb,
166 lfilter = lambda pkt: EAP in pkt and pkt[EAP].type == EAP_TYPE_TLS and \
167 pkt[EAP].code == EAP.REQUEST)
168
169 return True
170
A R Karthicka2e53d62016-02-19 17:38:30 -0800171 def eapTLS(self, code, pkt_id, flags = TLS_LENGTH_INCLUDED, data=""):
172 req_type = EAP_TYPE_TLS
173 if code in [EAP_SUCCESS, EAP_FAILURE]:
174 return pack("!BBH", code, pkt_id, 4)
175 else:
176 if flags & TLS_LENGTH_INCLUDED:
177 flags_dlen = pack("!BL", flags, len(data))
178 return pack("!BBHB", code, pkt_id, 5+len(flags_dlen)+len(data), req_type) + flags_dlen + data
179 flags_str = pack("!B", flags)
180 return pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data), req_type) + flags_str + data
181
A R Karthickaa10a202016-08-15 15:06:21 -0700182 def eapTLSFragment(self, code, pkt_id, frag, data="", data_len = 0):
183 req_type = EAP_TYPE_TLS
184 if frag == 0:
185 flags = TLS_LENGTH_INCLUDED | TLS_MORE_FRAGMENTS
186 elif frag > 0:
187 flags = TLS_MORE_FRAGMENTS
188 else:
189 #last fragment
190 flags = 0
191 if data_len == 0:
192 data_len = len(data)
193 if flags & TLS_LENGTH_INCLUDED:
194 flags_dlen = pack("!BL", flags, data_len)
195 return pack("!BBHB", code, pkt_id, 5+len(flags_dlen)+len(data), req_type) + flags_dlen + data
196 flags_str = pack("!B", flags)
197 return pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data), req_type) + flags_str + data
198
A R Karthicka2e53d62016-02-19 17:38:30 -0800199 def eapol_send(self, eapol_type, eap_payload):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -0800200 return sendp(self.llheader/self.eapol(eapol_type, eap_payload), iface=self.intf)
A R Karthicka2e53d62016-02-19 17:38:30 -0800201
202 def eapol_recv(self):
A R Karthickaa10a202016-08-15 15:06:21 -0700203 p = self.s.recv(self.max_recv_size)[14:]
A R Karthicka2e53d62016-02-19 17:38:30 -0800204 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
205 print "Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
206 assert_equal(pkt_type, EAPOL_EAPPACKET)
207 return p[4:]
208
A.R Karthickaa859b22017-06-12 14:50:35 -0700209 def eapol_scapy_recv(self, cb = None, lfilter = None, count = 1, timeout = 10):
Chetan Gaonker5b366302016-03-21 16:18:21 -0700210 def eapol_default_cb(pkt): pass
211 if cb is None:
212 cb = eapol_default_cb
A R Karthick05d9b5f2016-06-08 11:53:54 -0700213 return sniff(prn = cb, lfilter = lfilter, count = count, timeout = timeout, opened_socket = self.recv_sock)
Chetan Gaonker5b366302016-03-21 16:18:21 -0700214
A R Karthicka2e53d62016-02-19 17:38:30 -0800215 def eapol_start(self):
216 eap_payload = self.eap(EAPOL_START, 2)
217 return self.eapol_send(EAPOL_START, eap_payload)
218
A R Karthick307483c2016-06-06 17:05:19 -0700219 def eapol_logoff(self):
220 eap_payload = self.eap(EAPOL_LOGOFF, 2)
221 return self.eapol_send(EAPOL_LOGOFF, eap_payload)
222
A R Karthicka2e53d62016-02-19 17:38:30 -0800223 def eapol_id_req(self, pkt_id = 0, user = USER):
224 eap_payload = self.eap(EAP_RESPONSE, pkt_id, EAP_TYPE_ID, user)
225 return self.eapol_send(EAPOL_EAPPACKET, eap_payload)
226
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800227 def eap_md5_challenge_recv(self,rad_pwd):
228 PASS = rad_pwd
229 print 'Inside EAP MD5 Challenge Exchange'
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 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
232 print "EAPOL Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
233 code, pkt_id, eaplen = unpack("!BBH", p[4:8])
234 print "EAP Code %d, id %d, len %d" %(code, pkt_id, eaplen)
235 assert_equal(code, EAP_REQUEST)
236 reqtype = unpack("!B", p[8:9])[0]
237 reqdata = p[9:4+eaplen]
238 print 'Request type is %d' %(reqtype)
239 assert_equal(reqtype, EAP_TYPE_MD5)
240 challenge=pack("!B",pkt_id)+PASS+reqdata[1:]
241 print "Generating md5 challenge for %s" % challenge
242 return (challenge,pkt_id)
243
244 def eap_Status(self):
245 print 'Inside EAP Status'
A R Karthickaa10a202016-08-15 15:06:21 -0700246 p = self.s.recv(self.max_recv_size)[14:]
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800247 code, id, eaplen = unpack("!BBH", p[4:8])
248 return code
249
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000250 @classmethod
251 def eap_invalid_tls_packets_info(self, invalid_field_name = None, invalid_field_value = None):
A R Karthick76a497a2017-04-12 10:59:39 -0700252 log_test.info( 'Changing invalid field values in tls auth packets' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000253 if invalid_field_name == 'eapolTlsVersion':
254 global EAPOL_VERSION
A R Karthick76a497a2017-04-12 10:59:39 -0700255 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000256 EAPOL_VERSION = invalid_field_value
257 if invalid_field_name == 'eapolTlsType':
258 global EAP_TYPE_TLS
A R Karthick76a497a2017-04-12 10:59:39 -0700259 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000260 EAP_TYPE_TLS = invalid_field_value
261 if invalid_field_name == 'eapolTypeID':
262 global EAP_TYPE_ID
A R Karthick76a497a2017-04-12 10:59:39 -0700263 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000264 EAP_TYPE_ID = invalid_field_value
265 if invalid_field_name == 'eapolResponse':
266 global EAP_RESPONSE
A R Karthick76a497a2017-04-12 10:59:39 -0700267 log_test.info( 'Changing invalid field values in tls auth packets====== EAP TYPE TLS changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000268 EAP_RESPONSE = invalid_field_value
269
270
271 @classmethod
272 def eap_tls_packets_field_value_replace(self, invalid_field_name = None):
A R Karthick76a497a2017-04-12 10:59:39 -0700273 log_test.info( 'Changing invalid field values in tls auth packets' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000274 if invalid_field_name == 'eapolTlsVersion':
275 global EAPOL_VERSION
276 EAPOL_VERSION = 1
A R Karthick76a497a2017-04-12 10:59:39 -0700277 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000278 if invalid_field_name == 'eapolTlsType':
279 global EAP_TYPE_TLS
280 EAP_TYPE_TLS = 13
A R Karthick76a497a2017-04-12 10:59:39 -0700281 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000282 if invalid_field_name == 'eapolTypeID':
283 global EAP_TYPE_ID
284 EAP_TYPE_ID = 1
A R Karthick76a497a2017-04-12 10:59:39 -0700285 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )
Thangavelu K Sef6f0a52016-12-14 19:57:05 +0000286 if invalid_field_name == 'eapolResponse':
287 global EAP_RESPONSE
288 EAP_RESPONSE = 2
A R Karthick76a497a2017-04-12 10:59:39 -0700289 log_test.info( 'Changing invalid field values in tls auth packets====== version changing' )