blob: 0a2f8bdc255c17f3eb77715ddbe6e4c5686fe15b [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 Karthicka2e53d62016-02-19 17:38:30 -080018from socket import *
19from struct import *
A R Karthicka2e53d62016-02-19 17:38:30 -080020import sys
21from nose.tools import assert_equal, assert_not_equal, assert_raises, assert_true
22
23USER = "raduser"
24PASS = "radpass"
25WRONG_USER = "XXXX"
26WRONG_PASS = "XXXX"
27NO_USER = ""
28NO_PASS = ""
29DEV = "tap0"
30ETHERTYPE_PAE = 0x888e
31PAE_GROUP_ADDR = "\xff\xff\xff\xff\xff\xff"
32EAPOL_VERSION = 1
33EAPOL_EAPPACKET = 0
34EAPOL_START = 1
35EAPOL_LOGOFF = 2
36EAPOL_KEY = 3
37EAPOL_ASF = 4
38EAP_REQUEST = 1
39EAP_RESPONSE = 2
40EAP_SUCCESS = 3
41EAP_FAILURE = 4
42EAP_TYPE_ID = 1
43EAP_TYPE_MD5 = 4
44EAP_TYPE_MSCHAP = 26
45EAP_TYPE_TLS = 13
46cCertMsg = '\x0b\x00\x00\x03\x00\x00\x00'
47TLS_LENGTH_INCLUDED = 0x80
48
A R Karthicka2e53d62016-02-19 17:38:30 -080049class EapolPacket(object):
A R Karthick05d9b5f2016-06-08 11:53:54 -070050
A R Karthicka2e53d62016-02-19 17:38:30 -080051 def __init__(self, intf = 'veth0'):
52 self.intf = intf
53 self.s = None
54 self.max_payload_size = 1600
55
56 def setup(self):
57 self.s = socket(AF_PACKET, SOCK_RAW, htons(ETHERTYPE_PAE))
58 self.s.bind((self.intf, ETHERTYPE_PAE))
59 self.mymac = self.s.getsockname()[4]
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080060 self.llheader = Ether(dst = PAE_GROUP_ADDR, src = self.mymac, type = ETHERTYPE_PAE)
Chetan Gaonker5b366302016-03-21 16:18:21 -070061 self.recv_sock = L2Socket(iface = self.intf, type = ETHERTYPE_PAE)
A R Karthicka2e53d62016-02-19 17:38:30 -080062
63 def cleanup(self):
64 if self.s is not None:
65 self.s.close()
66 self.s = None
A R Karthick05d9b5f2016-06-08 11:53:54 -070067
A R Karthicka2e53d62016-02-19 17:38:30 -080068 def eapol(self, req_type, payload=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080069 return EAPOL(version = EAPOL_VERSION, type = req_type)/payload
A R Karthicka2e53d62016-02-19 17:38:30 -080070
71 def eap(self, code, pkt_id, req_type=0, data=""):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080072 return EAP(code = code, id = pkt_id, type = req_type)/data
A R Karthicka2e53d62016-02-19 17:38:30 -080073
74 def eapTLS(self, code, pkt_id, flags = TLS_LENGTH_INCLUDED, data=""):
75 req_type = EAP_TYPE_TLS
76 if code in [EAP_SUCCESS, EAP_FAILURE]:
77 return pack("!BBH", code, pkt_id, 4)
78 else:
79 if flags & TLS_LENGTH_INCLUDED:
80 flags_dlen = pack("!BL", flags, len(data))
81 return pack("!BBHB", code, pkt_id, 5+len(flags_dlen)+len(data), req_type) + flags_dlen + data
82 flags_str = pack("!B", flags)
83 return pack("!BBHB", code, pkt_id, 5+len(flags_str)+len(data), req_type) + flags_str + data
84
85 def eapol_send(self, eapol_type, eap_payload):
Chetan Gaonker35cb16f2016-03-02 03:05:28 -080086 return sendp(self.llheader/self.eapol(eapol_type, eap_payload), iface=self.intf)
A R Karthicka2e53d62016-02-19 17:38:30 -080087
88 def eapol_recv(self):
89 p = self.s.recv(self.max_payload_size)[14:]
90 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
91 print "Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
92 assert_equal(pkt_type, EAPOL_EAPPACKET)
93 return p[4:]
94
A R Karthick05d9b5f2016-06-08 11:53:54 -070095 def eapol_scapy_recv(self, cb = None, lfilter = None, count = 1, timeout = 5):
Chetan Gaonker5b366302016-03-21 16:18:21 -070096 def eapol_default_cb(pkt): pass
97 if cb is None:
98 cb = eapol_default_cb
A R Karthick05d9b5f2016-06-08 11:53:54 -070099 return sniff(prn = cb, lfilter = lfilter, count = count, timeout = timeout, opened_socket = self.recv_sock)
Chetan Gaonker5b366302016-03-21 16:18:21 -0700100
A R Karthicka2e53d62016-02-19 17:38:30 -0800101 def eapol_start(self):
102 eap_payload = self.eap(EAPOL_START, 2)
103 return self.eapol_send(EAPOL_START, eap_payload)
104
A R Karthick307483c2016-06-06 17:05:19 -0700105 def eapol_logoff(self):
106 eap_payload = self.eap(EAPOL_LOGOFF, 2)
107 return self.eapol_send(EAPOL_LOGOFF, eap_payload)
108
A R Karthicka2e53d62016-02-19 17:38:30 -0800109 def eapol_id_req(self, pkt_id = 0, user = USER):
110 eap_payload = self.eap(EAP_RESPONSE, pkt_id, EAP_TYPE_ID, user)
111 return self.eapol_send(EAPOL_EAPPACKET, eap_payload)
112
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -0800113 def eap_md5_challenge_recv(self,rad_pwd):
114 PASS = rad_pwd
115 print 'Inside EAP MD5 Challenge Exchange'
116 p = self.s.recv(self.max_payload_size)[14:]
117 vers,pkt_type,eapollen = unpack("!BBH",p[:4])
118 print "EAPOL Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
119 code, pkt_id, eaplen = unpack("!BBH", p[4:8])
120 print "EAP Code %d, id %d, len %d" %(code, pkt_id, eaplen)
121 assert_equal(code, EAP_REQUEST)
122 reqtype = unpack("!B", p[8:9])[0]
123 reqdata = p[9:4+eaplen]
124 print 'Request type is %d' %(reqtype)
125 assert_equal(reqtype, EAP_TYPE_MD5)
126 challenge=pack("!B",pkt_id)+PASS+reqdata[1:]
127 print "Generating md5 challenge for %s" % challenge
128 return (challenge,pkt_id)
129
130 def eap_Status(self):
131 print 'Inside EAP Status'
132 p = self.s.recv(self.max_payload_size)[14:]
133 code, id, eaplen = unpack("!BBH", p[4:8])
134 return code
135