blob: 1df45741b7ae4c8ed3d2e35fbfbe02e458a189b3 [file] [log] [blame]
Ari Saha89831742015-06-26 10:31:48 -07001/*
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01002 * Copyright 2017-present Open Networking Foundation
Ari Saha89831742015-06-26 10:31:48 -07003 *
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 */
alshabib6d527452016-06-01 18:00:47 -070016package org.opencord.aaa;
Ari Saha89831742015-06-26 10:31:48 -070017
Ari Saha89831742015-06-26 10:31:48 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Ari Saha89831742015-06-26 10:31:48 -070021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010023
Jonathan Harta46dddf2015-06-30 15:31:20 -070024import org.onlab.packet.EAP;
25import org.onlab.packet.EAPOL;
26import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070027import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070028import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070029import org.onlab.packet.RADIUS;
30import org.onlab.packet.RADIUSAttribute;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010031import org.onlab.packet.VlanId;
32
Ari Saha89831742015-06-26 10:31:48 -070033import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010035import org.onosproject.mastership.MastershipService;
36import org.onosproject.net.AnnotationKeys;
Ari Saha89831742015-06-26 10:31:48 -070037import org.onosproject.net.ConnectPoint;
38import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070039import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070040import org.onosproject.net.config.ConfigFactory;
41import org.onosproject.net.config.NetworkConfigEvent;
42import org.onosproject.net.config.NetworkConfigListener;
43import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010044import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070045import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070046import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070047import org.onosproject.net.packet.DefaultOutboundPacket;
48import org.onosproject.net.packet.InboundPacket;
49import org.onosproject.net.packet.OutboundPacket;
50import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070051import org.onosproject.net.packet.PacketProcessor;
52import org.onosproject.net.packet.PacketService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010053
54import org.opencord.olt.AccessDeviceService;
55import org.opencord.sadis.SubscriberAndDeviceInformation;
56import org.opencord.sadis.SubscriberAndDeviceInformationService;
57
Ari Saha89831742015-06-26 10:31:48 -070058import org.slf4j.Logger;
59
Ray Milkeyfcb623d2015-10-01 16:48:18 -070060import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010061
Ari Saha89831742015-06-26 10:31:48 -070062import static org.slf4j.LoggerFactory.getLogger;
63
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010064import java.net.InetAddress;
65import java.nio.ByteBuffer;
66
Ari Saha89831742015-06-26 10:31:48 -070067/**
Jonathan Harta46dddf2015-06-30 15:31:20 -070068 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -070069 */
70@Component(immediate = true)
Jonathan Hart092dfb22015-11-16 23:05:21 -080071public class AaaManager {
Charles Chandf7ff862017-01-20 11:22:05 -080072 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -070073
Ray Milkeyf61a24e2015-09-24 16:34:02 -070074 // for verbose output
75 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -070076
Ray Milkeyf61a24e2015-09-24 16:34:02 -070077 // a list of our dependencies :
78 // to register with ONOS as an application - described next
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -070081
Ray Milkeyf61a24e2015-09-24 16:34:02 -070082 // to receive Packet-in events that we'll respond to
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -070085
Ray Milkeyf61a24e2015-09-24 16:34:02 -070086 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -070087 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -070088
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010089 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected DeviceService deviceService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected SubscriberAndDeviceInformationService subsService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected MastershipService mastershipService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected AccessDeviceService accessDeviceService;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700100
101 // NAS IP address
102 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100103
104 // self MAC address
105 protected static String nasMacAddress;
106
107 // Parsed RADIUS server addresses
108 protected InetAddress radiusIpAddress;
109
110 // MAC address of RADIUS server or net hop router
111 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700112
113 // RADIUS server secret
114 protected String radiusSecret;
115
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100116 // NAS Identifier
117 protected String nasId;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700118
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100119 // bindings
120 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700121
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700122 // our application-specific event handler
123 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700124
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700125 // our unique identifier
126 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700127
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100128 // Setup specific customization/attributes on the RADIUS packets
129 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700130
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100131 // packet customizer to use
132 private String customizer;
133
134 // Type of connection to use to communicate with Radius server, options are
135 // "socket" or "packet_out"
136 private String radiusConnectionType;
137
138 // Object for the spcific type of communication with the RADIUS
139 // server, socket based or packet_out based
140 RadiusCommunicator impl = null;
141
142 // latest configuration
143 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700144
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700145 // Configuration properties factory
146 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800147 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
148 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700149 "AAA") {
150 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800151 public AaaConfig createConfig() {
152 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700153 }
154 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700155
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700156 // Listener for config changes
157 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700158
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700159 /**
160 * Builds an EAPOL packet based on the given parameters.
161 *
162 * @param dstMac destination MAC address
163 * @param srcMac source MAC address
164 * @param vlan vlan identifier
165 * @param eapolType EAPOL type
166 * @param eap EAP payload
167 * @return Ethernet frame
168 */
169 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100170 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700171
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700172 Ethernet eth = new Ethernet();
173 eth.setDestinationMACAddress(dstMac.toBytes());
174 eth.setSourceMACAddress(srcMac.toBytes());
175 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
176 if (vlan != Ethernet.VLAN_UNTAGGED) {
177 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100178 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700179 }
180 //eapol header
181 EAPOL eapol = new EAPOL();
182 eapol.setEapolType(eapolType);
183 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700184
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700185 //eap part
186 eapol.setPayload(eap);
187
188 eth.setPayload(eapol);
189 eth.setPad(true);
190 return eth;
191 }
Ari Saha89831742015-06-26 10:31:48 -0700192
Ari Saha89831742015-06-26 10:31:48 -0700193 @Activate
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700194 public void activate() {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700195 netCfgService.registerConfigFactory(factory);
Charles Chandf7ff862017-01-20 11:22:05 -0800196 appId = coreService.registerApplication(APP_NAME);
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700197
Jonathan Hart092dfb22015-11-16 23:05:21 -0800198 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700199
Ari Saha89831742015-06-26 10:31:48 -0700200 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700201 packetService.addProcessor(processor, PacketProcessor.director(2));
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100202
203 customInfo = new CustomizationInfo(subsService, deviceService);
204
205 switch (customizer.toLowerCase()) {
206 case "sample":
207 pktCustomizer = new SamplePacketCustomizer(customInfo);
208 log.info("Created SamplePacketCustomizer");
209 break;
210 default:
211 pktCustomizer = new PacketCustomizer(customInfo);
212 log.info("Created default PacketCustomizer");
213 break;
214 }
215
216 if (radiusConnectionType.toLowerCase().equals("socket")) {
217 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
218 } else {
219 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
220 deviceService, subsService, pktCustomizer, this);
221 }
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700222
223 StateMachine.initializeMaps();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100224 StateMachine.setAccessDeviceService(accessDeviceService);
Ari Saha89831742015-06-26 10:31:48 -0700225
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100226 impl.initializeLocalState(newCfg);
alshabib27afc1d2016-12-23 00:33:58 -0800227 netCfgService.addListener(cfgListener);
228
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100229 impl.requestIntercepts();
230
Jian Li13c67162015-12-09 13:20:34 -0800231 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700232 }
233
234 @Deactivate
235 public void deactivate() {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100236 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700237 // de-register and null our handler
238 packetService.removeProcessor(processor);
239 processor = null;
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700240 StateMachine.destroyMaps();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100241
242 impl.deactivate();
243
Jian Li13c67162015-12-09 13:20:34 -0800244 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700245 }
246
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100247 /**
248 * Send RADIUS packet to the RADIUS server.
249 *
250 * @param radiusPacket RADIUS packet to be sent to server.
251 * @param inPkt Incoming EAPOL packet
252 */
253 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
254 impl.sendRadiusPacket(radiusPacket, inPkt);
255 }
Ray Milkey967776a2015-10-07 14:37:17 -0700256
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100257 /**
258 * Handles RADIUS packets.
259 *
260 * @param radiusPacket RADIUS packet coming from the RADIUS server.
261 * @throws StateMachineException if an illegal state transition is triggered
262 */
263 public void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException {
264 StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
265 if (stateMachine == null) {
266 log.error("Invalid session identifier {}, exiting...", radiusPacket.getIdentifier());
267 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700268 }
Ari Saha89831742015-06-26 10:31:48 -0700269
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100270 EAP eapPayload;
271 Ethernet eth;
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700272
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100273 switch (radiusPacket.getCode()) {
274 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
275 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
276 byte[] challengeState = null;
277 if (radiusAttrState != null) {
278 challengeState = radiusAttrState.getValue();
279 }
280 eapPayload = radiusPacket.decapsulateMessage();
281 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
282 eth = buildEapolResponse(stateMachine.supplicantAddress(),
283 MacAddress.valueOf(nasMacAddress),
284 stateMachine.vlanId(),
285 EAPOL.EAPOL_PACKET,
286 eapPayload, stateMachine.priorityCode());
287 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
288 break;
289 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
290 //send an EAPOL - Success to the supplicant.
291 byte[] eapMessageSuccess =
292 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
293 eapPayload = new EAP();
294 eapPayload = (EAP) eapPayload.deserialize(eapMessageSuccess, 0, eapMessageSuccess.length);
295 eth = buildEapolResponse(stateMachine.supplicantAddress(),
296 MacAddress.valueOf(nasMacAddress),
297 stateMachine.vlanId(),
298 EAPOL.EAPOL_PACKET,
299 eapPayload, stateMachine.priorityCode());
300 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
301
302 stateMachine.authorizeAccess();
303
304 break;
305 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
306 //send an EAPOL - Failure to the supplicant.
307 byte[] eapMessageFailure;
308 eapPayload = new EAP();
309 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
310 if (radiusAttrEap == null) {
311 eapPayload.setCode(EAP.FAILURE);
312 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
313 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
314 } else {
315 eapMessageFailure = radiusAttrEap.getValue();
316 eapPayload = (EAP) eapPayload.deserialize(eapMessageFailure, 0, eapMessageFailure.length);
317 }
318 eth = buildEapolResponse(stateMachine.supplicantAddress(),
319 MacAddress.valueOf(nasMacAddress),
320 stateMachine.vlanId(),
321 EAPOL.EAPOL_PACKET,
322 eapPayload, stateMachine.priorityCode());
323 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
324 stateMachine.denyAccess();
325
326 break;
327 default:
328 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
329 }
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700330 }
331
Ray Milkey967776a2015-10-07 14:37:17 -0700332 /**
333 * Send the ethernet packet to the supplicant.
334 *
335 * @param ethernetPkt the ethernet packet
336 * @param connectPoint the connect point to send out
337 */
338 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) {
339 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
340 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
341 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
342 packetService.emit(packet);
343 }
344
Ari Saha89831742015-06-26 10:31:48 -0700345 // our handler defined as a private inner class
346
347 /**
348 * Packet processor responsible for forwarding packets along their paths.
349 */
350 private class ReactivePacketProcessor implements PacketProcessor {
351 @Override
352 public void process(PacketContext context) {
353
354 // Extract the original Ethernet frame from the packet information
355 InboundPacket pkt = context.inPacket();
356 Ethernet ethPkt = pkt.parsed();
357 if (ethPkt == null) {
358 return;
359 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100360
Ray Milkeyf51eba22015-09-25 10:24:23 -0700361 try {
362 // identify if incoming packet comes from supplicant (EAP) or RADIUS
363 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
364 case EAPOL:
365 handleSupplicantPacket(context.inPacket());
366 break;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700367 default:
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100368 // any other packets let the specific implementation handle
369 impl.handlePacketFromServer(context);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700370 }
Ray Milkey967776a2015-10-07 14:37:17 -0700371 } catch (StateMachineException e) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100372 log.warn("Unable to process packet:", e);
Ari Saha89831742015-06-26 10:31:48 -0700373 }
374 }
375
Ray Milkey9eb293f2015-09-30 15:09:17 -0700376 /**
377 * Creates and initializes common fields of a RADIUS packet.
378 *
Ray Milkey967776a2015-10-07 14:37:17 -0700379 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700380 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700381 * @return RADIUS packet
382 */
Ray Milkey967776a2015-10-07 14:37:17 -0700383 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700384 RADIUS radiusPayload =
385 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
386 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700387
388 // set Request Authenticator in StateMachine
389 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
390
Ray Milkey9eb293f2015-09-30 15:09:17 -0700391 radiusPayload.setIdentifier(identifier);
392 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700393 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700394
395 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800396 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700397
398 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700399
400 return radiusPayload;
401 }
Ari Saha89831742015-06-26 10:31:48 -0700402
403 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700404 * Handles PAE packets (supplicant).
405 *
406 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700407 */
Ray Milkeyf51eba22015-09-25 10:24:23 -0700408 private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700409 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700410 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800411 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700412
Jonathan Harta46dddf2015-06-30 15:31:20 -0700413 DeviceId deviceId = inPacket.receivedFrom().deviceId();
414 PortNumber portNumber = inPacket.receivedFrom().port();
Ari Saha89831742015-06-26 10:31:48 -0700415 String sessionId = deviceId.toString() + portNumber.toString();
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700416 StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
417 if (stateMachine == null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100418 if (deviceService != null) {
419 String nasPortId = deviceService.getPort(inPacket.receivedFrom()).
420 annotations().value(AnnotationKeys.PORT_NAME);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700421
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100422 SubscriberAndDeviceInformation subscriber =
423 subsService.get(nasPortId);
424 if (subscriber != null) {
425 stateMachine = new StateMachine(sessionId, subscriber.cTag());
Amit Ghoshcf39d972017-08-16 08:15:20 +0100426 } else {
427 log.error("Could not create new state machine for {}", nasPortId);
428 return;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100429 }
430 } else {
431 stateMachine = new StateMachine(sessionId, VlanId.vlanId((short) 0));
432 }
433 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700434
435 EAPOL eapol = (EAPOL) ethPkt.getPayload();
Ari Saha89831742015-06-26 10:31:48 -0700436
437 switch (eapol.getEapolType()) {
438 case EAPOL.EAPOL_START:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700439 stateMachine.start();
440 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Ari Saha89831742015-06-26 10:31:48 -0700441
Ray Milkeyf51eba22015-09-25 10:24:23 -0700442 //send an EAP Request/Identify to the supplicant
443 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100444 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
445 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
446 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800447 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700448 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100449 eapPayload, stateMachine.priorityCode());
Jonathan Hart092dfb22015-11-16 23:05:21 -0800450 stateMachine.setSupplicantAddress(srcMac);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700451 stateMachine.setVlanId(ethPkt.getVlanID());
Ari Saha89831742015-06-26 10:31:48 -0700452
Ray Milkey967776a2015-10-07 14:37:17 -0700453 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
Ari Saha89831742015-06-26 10:31:48 -0700454
455 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800456 case EAPOL.EAPOL_LOGOFF:
Ray Milkeyb34b4962016-01-04 10:24:43 -0800457 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
458 stateMachine.logoff();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800459 }
460
461 break;
Ari Saha89831742015-06-26 10:31:48 -0700462 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700463 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700464 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700465 EAP eapPacket = (EAP) eapol.getPayload();
466
467 byte dataType = eapPacket.getDataType();
468 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700469
Ray Milkey9eb293f2015-09-30 15:09:17 -0700470 case EAP.ATTR_IDENTITY:
471 // request id access to RADIUS
472 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700473
Ray Milkey967776a2015-10-07 14:37:17 -0700474 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100475 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800476 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700477
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100478 sendRadiusPacket(radiusPayload, inPacket);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700479
Ray Milkey9eb293f2015-09-30 15:09:17 -0700480 // change the state to "PENDING"
481 stateMachine.requestAccess();
482 break;
Ari Saha89831742015-06-26 10:31:48 -0700483 case EAP.ATTR_MD5:
Ray Milkey9eb293f2015-09-30 15:09:17 -0700484 // verify if the EAP identifier corresponds to the
485 // challenge identifier from the client state
486 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700487 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700488 //send the RADIUS challenge response
Ray Milkey967776a2015-10-07 14:37:17 -0700489 radiusPayload =
490 getRadiusPayload(stateMachine,
491 stateMachine.identifier(),
492 eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100493 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700494
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800495 if (stateMachine.challengeState() != null) {
496 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
497 stateMachine.challengeState());
498 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800499 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100500 sendRadiusPacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700501 }
502 break;
503 case EAP.ATTR_TLS:
Ray Milkey9eb293f2015-09-30 15:09:17 -0700504 // request id access to RADIUS
Ray Milkey967776a2015-10-07 14:37:17 -0700505 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100506 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700507
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800508 if (stateMachine.challengeState() != null) {
509 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
510 stateMachine.challengeState());
511 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700512 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700513
Jonathan Hart092dfb22015-11-16 23:05:21 -0800514 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100515 sendRadiusPacket(radiusPayload, inPacket);
Ray Milkey5493b512015-10-21 12:13:49 -0700516
Ray Milkeyf3790b82015-10-21 16:28:08 -0700517 if (stateMachine.state() != StateMachine.STATE_PENDING) {
518 stateMachine.requestAccess();
519 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700520
Ari Saha89831742015-06-26 10:31:48 -0700521 break;
522 default:
523 return;
524 }
525 break;
526 default:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700527 log.trace("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700528 }
529 }
Ray Milkey967776a2015-10-07 14:37:17 -0700530 }
531
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100532 /**
533 * Configuration Listener, handles change in configuration.
534 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700535 private class InternalConfigListener implements NetworkConfigListener {
536
537 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800538 * Reconfigures the AAA application according to the
539 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700540 *
541 * @param cfg configuration object
542 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800543 private void reconfigureNetwork(AaaConfig cfg) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100544
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700545 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800546 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700547 } else {
548 newCfg = cfg;
549 }
550 if (newCfg.nasIp() != null) {
551 nasIpAddress = newCfg.nasIp();
552 }
553 if (newCfg.radiusIp() != null) {
554 radiusIpAddress = newCfg.radiusIp();
555 }
556 if (newCfg.radiusMac() != null) {
557 radiusMacAddress = newCfg.radiusMac();
558 }
559 if (newCfg.nasMac() != null) {
560 nasMacAddress = newCfg.nasMac();
561 }
562 if (newCfg.radiusSecret() != null) {
563 radiusSecret = newCfg.radiusSecret();
564 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100565
566 radiusConnectionType = newCfg.radiusConnectionType();
567 customizer = newCfg.radiusPktCustomizer();
568
569 if (impl != null) {
570 impl.clearLocalState();
571 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -0700572 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700573 }
574
575 @Override
576 public void event(NetworkConfigEvent event) {
577
578 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
579 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -0800580 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700581
Jonathan Hart092dfb22015-11-16 23:05:21 -0800582 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700583 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100584
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700585 log.info("Reconfigured");
586 }
587 }
588 }
Ari Saha89831742015-06-26 10:31:48 -0700589}