blob: 32f46244ea4eb561131b705a014febe30334b5d5 [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 */
Matteo Scandolocf847b82019-04-26 15:00:00 -070016package org.opencord.aaa.impl;
Ari Saha89831742015-06-26 10:31:48 -070017
Saurav Das987441a2018-09-18 16:33:47 -070018import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.net.InetAddress;
kartikey dubeye1545422019-05-22 12:53:45 +000022import java.net.UnknownHostException;
Saurav Das987441a2018-09-18 16:33:47 -070023import java.nio.ByteBuffer;
24import java.util.Map;
kartikey dubeye1545422019-05-22 12:53:45 +000025import java.util.Dictionary;
26import java.util.HashSet;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000027import java.util.Arrays;
Saurav Das987441a2018-09-18 16:33:47 -070028
Jonathan Hart932bedc2018-07-12 13:46:09 -070029import org.apache.commons.lang3.builder.ToStringBuilder;
Ari Saha89831742015-06-26 10:31:48 -070030import org.apache.felix.scr.annotations.Component;
31import org.apache.felix.scr.annotations.Deactivate;
kartikey dubeye1545422019-05-22 12:53:45 +000032import org.apache.felix.scr.annotations.Property;
Ari Saha89831742015-06-26 10:31:48 -070033import org.apache.felix.scr.annotations.Reference;
34import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart5db44532018-07-12 18:13:54 -070035import org.apache.felix.scr.annotations.Service;
Jonathan Hart4731dd92018-05-02 17:30:05 -070036import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070037import org.onlab.packet.EAP;
38import org.onlab.packet.EAPOL;
39import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070040import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070041import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070042import org.onlab.packet.RADIUS;
43import org.onlab.packet.RADIUSAttribute;
kartikey dubeye1545422019-05-22 12:53:45 +000044import org.onlab.util.Tools;
45import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070046import org.onosproject.core.ApplicationId;
47import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070048import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010049import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070050import org.onosproject.net.ConnectPoint;
51import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070052import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070053import org.onosproject.net.config.ConfigFactory;
54import org.onosproject.net.config.NetworkConfigEvent;
55import org.onosproject.net.config.NetworkConfigListener;
56import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010057import org.onosproject.net.device.DeviceEvent;
58import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010059import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070060import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070061import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070062import org.onosproject.net.packet.DefaultOutboundPacket;
63import org.onosproject.net.packet.InboundPacket;
64import org.onosproject.net.packet.OutboundPacket;
65import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070066import org.onosproject.net.packet.PacketProcessor;
67import org.onosproject.net.packet.PacketService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070068import org.opencord.aaa.AaaConfig;
69import org.opencord.aaa.AuthenticationEvent;
70import org.opencord.aaa.AuthenticationEventListener;
71import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000072import org.opencord.aaa.AuthenticationStatisticsEvent;
73import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070074import org.opencord.aaa.RadiusCommunicator;
75import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000076import org.opencord.sadis.BaseInformationService;
77import org.opencord.sadis.SadisService;
78import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000079import org.osgi.service.component.ComponentContext;
Kartikey Dubeyf72e1952019-06-24 07:09:00 +000080import org.apache.felix.scr.annotations.Modified;
81import org.apache.felix.scr.annotations.Activate;
Ari Saha89831742015-06-26 10:31:48 -070082import org.slf4j.Logger;
kartikey dubeye1545422019-05-22 12:53:45 +000083import com.google.common.base.Strings;
Ari Saha89831742015-06-26 10:31:48 -070084
kartikey dubeye1545422019-05-22 12:53:45 +000085import java.util.concurrent.Executors;
86import java.util.concurrent.ScheduledExecutorService;
87import java.util.concurrent.ScheduledFuture;
88import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000089
90import javax.crypto.Mac;
91import javax.crypto.spec.SecretKeySpec;
Ari Saha89831742015-06-26 10:31:48 -070092/**
Jonathan Harta46dddf2015-06-30 15:31:20 -070093 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -070094 */
Jonathan Hart5db44532018-07-12 18:13:54 -070095@Service
Ari Saha89831742015-06-26 10:31:48 -070096@Component(immediate = true)
Jonathan Hart5db44532018-07-12 18:13:54 -070097public class AaaManager
98 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
99 implements AuthenticationService {
100
Charles Chandf7ff862017-01-20 11:22:05 -0800101 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -0700102
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700103 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700104
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700107
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700110
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700112 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700113
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected DeviceService deviceService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000118 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected MastershipService mastershipService;
122
kartikey dubeye1545422019-05-22 12:53:45 +0000123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000125
kartikey dubeye1545422019-05-22 12:53:45 +0000126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected ComponentConfigService cfgService;
128
129 protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
130 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100131 private final DeviceListener deviceListener = new InternalDeviceListener();
132
kartikey dubeye1545422019-05-22 12:53:45 +0000133 private static final int DEFAULT_REPEAT_DELAY = 20;
134 @Property(name = "statisticsGenerationEvent", intValue = DEFAULT_REPEAT_DELAY,
135 label = "statisticsGenerationEvent")
136 private int statisticsGenerationEvent = DEFAULT_REPEAT_DELAY;
137
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700138 // NAS IP address
139 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100140
141 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700142 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100143
144 // Parsed RADIUS server addresses
145 protected InetAddress radiusIpAddress;
146
147 // MAC address of RADIUS server or net hop router
148 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700149
150 // RADIUS server secret
151 protected String radiusSecret;
152
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100153 // bindings
154 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700155
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700156 // our application-specific event handler
157 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700158
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700159 // our unique identifier
160 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700161
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100162 // Setup specific customization/attributes on the RADIUS packets
163 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700164
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100165 // packet customizer to use
166 private String customizer;
167
168 // Type of connection to use to communicate with Radius server, options are
169 // "socket" or "packet_out"
170 private String radiusConnectionType;
171
Jonathan Hart5db44532018-07-12 18:13:54 -0700172 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100173 // server, socket based or packet_out based
174 RadiusCommunicator impl = null;
175
176 // latest configuration
177 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700178
kartikey dubeye1545422019-05-22 12:53:45 +0000179 ScheduledFuture<?> scheduledFuture;
180
181 ScheduledExecutorService executor;
182 String configuredAaaServerAddress;
183 HashSet<Byte> outPacketSet = new HashSet<Byte>();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700184 // Configuration properties factory
185 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800186 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
187 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700188 "AAA") {
189 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800190 public AaaConfig createConfig() {
191 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700192 }
193 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700194
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700195 // Listener for config changes
196 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700197
Jonathan Hart5db44532018-07-12 18:13:54 -0700198 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
199
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700200 /**
201 * Builds an EAPOL packet based on the given parameters.
202 *
203 * @param dstMac destination MAC address
204 * @param srcMac source MAC address
205 * @param vlan vlan identifier
206 * @param eapolType EAPOL type
207 * @param eap EAP payload
208 * @return Ethernet frame
209 */
210 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100211 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700212
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700213 Ethernet eth = new Ethernet();
214 eth.setDestinationMACAddress(dstMac.toBytes());
215 eth.setSourceMACAddress(srcMac.toBytes());
216 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
217 if (vlan != Ethernet.VLAN_UNTAGGED) {
218 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100219 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700220 }
221 //eapol header
222 EAPOL eapol = new EAPOL();
223 eapol.setEapolType(eapolType);
224 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700225
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700226 //eap part
227 eapol.setPayload(eap);
228
229 eth.setPayload(eapol);
230 eth.setPad(true);
231 return eth;
232 }
Ari Saha89831742015-06-26 10:31:48 -0700233
Ari Saha89831742015-06-26 10:31:48 -0700234 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000235 public void activate(ComponentContext context) {
Charles Chandf7ff862017-01-20 11:22:05 -0800236 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart5db44532018-07-12 18:13:54 -0700237 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400238 netCfgService.addListener(cfgListener);
239 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000240 cfgService.registerProperties(getClass());
241 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000242 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530243 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800244 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400245 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530246 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700247 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700248 packetService.addProcessor(processor, PacketProcessor.director(2));
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700249 StateMachine.initializeMaps();
Jonathan Hart5db44532018-07-12 18:13:54 -0700250 StateMachine.setDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100251 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100252 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100253 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000254 getConfiguredAaaServerAddress();
255 authenticationStatisticsPublisher =
256 new AuthenticationStatisticsEventPublisher();
257 executor = Executors.newScheduledThreadPool(1);
258 scheduledFuture = executor.scheduleAtFixedRate(authenticationStatisticsPublisher,
259 0, statisticsGenerationEvent, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100260
Jian Li13c67162015-12-09 13:20:34 -0800261 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700262 }
263
264 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000265 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100266 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700267 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530268 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000269 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700270 StateMachine.unsetDelegate(delegate);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530271 StateMachine.destroyMaps();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100272 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100273 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700274 eventDispatcher.removeSink(AuthenticationEvent.class);
kartikey dubeye1545422019-05-22 12:53:45 +0000275 scheduledFuture.cancel(true);
276 executor.shutdown();
Jian Li13c67162015-12-09 13:20:34 -0800277 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700278 }
279
kartikey dubeye1545422019-05-22 12:53:45 +0000280 @Modified
281 public void modified(ComponentContext context) {
282 Dictionary<?, ?> properties = context.getProperties();
283 String s = Tools.get(properties, "statisticsGenerationEvent");
284 statisticsGenerationEvent = Strings.isNullOrEmpty(s) ? DEFAULT_REPEAT_DELAY : Integer.parseInt(s.trim());
285 }
286
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530287 private void configureRadiusCommunication() {
288 if (radiusConnectionType.toLowerCase().equals("socket")) {
289 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
290 } else {
291 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
292 deviceService, subsService, pktCustomizer, this);
293 }
294 }
295
296 private void configurePacketCustomizer() {
297 switch (customizer.toLowerCase()) {
298 case "sample":
299 pktCustomizer = new SamplePacketCustomizer(customInfo);
300 log.info("Created SamplePacketCustomizer");
301 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800302 case "att":
303 pktCustomizer = new AttPacketCustomizer(customInfo);
304 log.info("Created AttPacketCustomizer");
305 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530306 default:
307 pktCustomizer = new PacketCustomizer(customInfo);
308 log.info("Created default PacketCustomizer");
309 break;
310 }
311 }
312
kartikey dubeye1545422019-05-22 12:53:45 +0000313 private void getConfiguredAaaServerAddress() {
314 try {
315 InetAddress address;
316 if (newCfg.radiusHostName() != null) {
317 address = InetAddress.getByName(newCfg.radiusHostName());
318 } else {
319 address = newCfg.radiusIp();
320 }
321
322 configuredAaaServerAddress = address.getHostAddress();
323 } catch (UnknownHostException uhe) {
324 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
325 }
326 }
327
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000328 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
329 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000330 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
331 }
332 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000333
334 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
335 byte[] newHash = new byte[16];
336 Arrays.fill(newHash, (byte) 0);
337 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
338 byte[] authenticator = radiusPacket.getAuthenticator();
339 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
340 radiusPacket.setAuthenticator(requestAuthenticator);
341 // Calculate the MD5 HMAC based on the message
342 try {
343 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
344 Mac mac = Mac.getInstance("HmacMD5");
345 mac.init(keySpec);
346 newHash = mac.doFinal(radiusPacket.serialize());
347 } catch (Exception e) {
348 log.error("Failed to generate message authenticator: {}", e.getMessage());
349 }
350 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
351 radiusPacket.setAuthenticator(authenticator);
352 // Compare the calculated Message-Authenticator with the one in the message
353 return Arrays.equals(newHash, messageAuthenticator);
354 }
kartikey dubeye1545422019-05-22 12:53:45 +0000355 public void checkForPacketFromUnknownServer(String hostAddress) {
356 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000357 getConfiguredAaaServerAddress();
358 if (!hostAddress.equals(configuredAaaServerAddress)) {
359 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
360 }
kartikey dubeye1545422019-05-22 12:53:45 +0000361 }
362 }
363
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100364 /**
365 * Send RADIUS packet to the RADIUS server.
366 *
367 * @param radiusPacket RADIUS packet to be sent to server.
368 * @param inPkt Incoming EAPOL packet
369 */
370 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000371 outPacketSet.add(radiusPacket.getIdentifier());
372 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
373 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100374 impl.sendRadiusPacket(radiusPacket, inPkt);
375 }
Ray Milkey967776a2015-10-07 14:37:17 -0700376
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100377 /**
378 * Handles RADIUS packets.
379 *
380 * @param radiusPacket RADIUS packet coming from the RADIUS server.
381 * @throws StateMachineException if an illegal state transition is triggered
Jonathan Hart4731dd92018-05-02 17:30:05 -0700382 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100383 */
Jonathan Hart4731dd92018-05-02 17:30:05 -0700384 public void handleRadiusPacket(RADIUS radiusPacket)
385 throws StateMachineException, DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700386 if (log.isTraceEnabled()) {
387 log.trace("Received RADIUS packet {}", radiusPacket);
388 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100389 StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
390 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700391 log.error("Invalid packet identifier {}, could not find corresponding "
392 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000393 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
394 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100395 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700396 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100397 EAP eapPayload;
398 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000399 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
kartikey dubeye1545422019-05-22 12:53:45 +0000400 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
401 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
402 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
403 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100404 switch (radiusPacket.getCode()) {
405 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400406 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100407 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
408 byte[] challengeState = null;
409 if (radiusAttrState != null) {
410 challengeState = radiusAttrState.getValue();
411 }
412 eapPayload = radiusPacket.decapsulateMessage();
413 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
414 eth = buildEapolResponse(stateMachine.supplicantAddress(),
415 MacAddress.valueOf(nasMacAddress),
416 stateMachine.vlanId(),
417 EAPOL.EAPOL_PACKET,
418 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400419 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000420 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000421 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100422 break;
423 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400424 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100425 //send an EAPOL - Success to the supplicant.
426 byte[] eapMessageSuccess =
427 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700428 eapPayload = EAP.deserializer().deserialize(
429 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100430 eth = buildEapolResponse(stateMachine.supplicantAddress(),
431 MacAddress.valueOf(nasMacAddress),
432 stateMachine.vlanId(),
433 EAPOL.EAPOL_PACKET,
434 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400435 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000436 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
437 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100438
439 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000440 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100441 break;
442 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400443 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100444 //send an EAPOL - Failure to the supplicant.
445 byte[] eapMessageFailure;
446 eapPayload = new EAP();
447 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
448 if (radiusAttrEap == null) {
449 eapPayload.setCode(EAP.FAILURE);
450 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
451 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
452 } else {
453 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700454 eapPayload = EAP.deserializer().deserialize(
455 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100456 }
457 eth = buildEapolResponse(stateMachine.supplicantAddress(),
458 MacAddress.valueOf(nasMacAddress),
459 stateMachine.vlanId(),
460 EAPOL.EAPOL_PACKET,
461 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400462 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000463 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
464 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
465
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100466 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000467 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100468 break;
469 default:
470 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000471 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100472 }
kartikey dubeye1545422019-05-22 12:53:45 +0000473 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700474 }
475
Ray Milkey967776a2015-10-07 14:37:17 -0700476 /**
477 * Send the ethernet packet to the supplicant.
478 *
479 * @param ethernetPkt the ethernet packet
480 * @param connectPoint the connect point to send out
481 */
Shubham Sharmac155ef82019-07-11 12:12:41 +0000482 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700483 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
484 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
485 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharmac155ef82019-07-11 12:12:41 +0000486 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
487 EAP eapPkt = (EAP) eap.getPayload();
Saurav Das987441a2018-09-18 16:33:47 -0700488 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700489 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
490 eap, ethernetPkt, connectPoint);
491 }
Ray Milkey967776a2015-10-07 14:37:17 -0700492 packetService.emit(packet);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000493 if (isChallengeResponse) {
494 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
495 }
Ray Milkey967776a2015-10-07 14:37:17 -0700496 }
497
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400498 @Override
499 public String toString() {
500 return ToStringBuilder.reflectionToString(this);
501 }
502
Ari Saha89831742015-06-26 10:31:48 -0700503 // our handler defined as a private inner class
504
505 /**
506 * Packet processor responsible for forwarding packets along their paths.
507 */
508 private class ReactivePacketProcessor implements PacketProcessor {
509 @Override
510 public void process(PacketContext context) {
511
512 // Extract the original Ethernet frame from the packet information
513 InboundPacket pkt = context.inPacket();
514 Ethernet ethPkt = pkt.parsed();
515 if (ethPkt == null) {
516 return;
517 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100518
Ray Milkeyf51eba22015-09-25 10:24:23 -0700519 try {
520 // identify if incoming packet comes from supplicant (EAP) or RADIUS
521 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
522 case EAPOL:
523 handleSupplicantPacket(context.inPacket());
524 break;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700525 default:
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100526 // any other packets let the specific implementation handle
527 impl.handlePacketFromServer(context);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700528 }
Ray Milkey967776a2015-10-07 14:37:17 -0700529 } catch (StateMachineException e) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100530 log.warn("Unable to process packet:", e);
Ari Saha89831742015-06-26 10:31:48 -0700531 }
532 }
533
Ray Milkey9eb293f2015-09-30 15:09:17 -0700534 /**
535 * Creates and initializes common fields of a RADIUS packet.
536 *
Ray Milkey967776a2015-10-07 14:37:17 -0700537 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700538 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700539 * @return RADIUS packet
540 */
Ray Milkey967776a2015-10-07 14:37:17 -0700541 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700542 RADIUS radiusPayload =
543 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
544 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700545
546 // set Request Authenticator in StateMachine
547 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
548
Ray Milkey9eb293f2015-09-30 15:09:17 -0700549 radiusPayload.setIdentifier(identifier);
550 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700551 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700552
553 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800554 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700555
556 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700557
558 return radiusPayload;
559 }
Ari Saha89831742015-06-26 10:31:48 -0700560
561 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700562 * Handles PAE packets (supplicant).
563 *
564 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700565 */
Ray Milkeyf51eba22015-09-25 10:24:23 -0700566 private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700567 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700568 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800569 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700570
Jonathan Harta46dddf2015-06-30 15:31:20 -0700571 DeviceId deviceId = inPacket.receivedFrom().deviceId();
572 PortNumber portNumber = inPacket.receivedFrom().port();
Ari Saha89831742015-06-26 10:31:48 -0700573 String sessionId = deviceId.toString() + portNumber.toString();
Saurav Das987441a2018-09-18 16:33:47 -0700574 EAPOL eapol = (EAPOL) ethPkt.getPayload();
575 if (log.isTraceEnabled()) {
576 log.trace("Received EAPOL packet {} in enclosing packet {} from "
577 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
578 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100579 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700580
Saurav Das987441a2018-09-18 16:33:47 -0700581 StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
582 if (stateMachine == null) {
583 log.debug("Creating new state machine for sessionId: {} for "
584 + "dev/port: {}/{}", sessionId, deviceId, portNumber);
585 stateMachine = new StateMachine(sessionId);
586 } else {
587 log.debug("Using existing state-machine for sessionId: {}", sessionId);
588 }
589
Ari Saha89831742015-06-26 10:31:48 -0700590 switch (eapol.getEapolType()) {
591 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400592 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700593 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Jonathan Hart5db44532018-07-12 18:13:54 -0700594 stateMachine.start();
Shubham Sharmac155ef82019-07-11 12:12:41 +0000595 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700596 //send an EAP Request/Identify to the supplicant
597 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100598 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
599 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
600 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800601 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700602 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100603 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400604
Jonathan Hart092dfb22015-11-16 23:05:21 -0800605 stateMachine.setSupplicantAddress(srcMac);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700606 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400607 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000608 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Ari Saha89831742015-06-26 10:31:48 -0700609
610 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800611 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400612 log.debug("EAP packet: EAPOL_LOGOFF");
Ray Milkeyb34b4962016-01-04 10:24:43 -0800613 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
614 stateMachine.logoff();
Shubham Sharmac155ef82019-07-11 12:12:41 +0000615 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800616 }
617
618 break;
Ari Saha89831742015-06-26 10:31:48 -0700619 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700620 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700621 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700622 EAP eapPacket = (EAP) eapol.getPayload();
623
624 byte dataType = eapPacket.getDataType();
625 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700626
Ray Milkey9eb293f2015-09-30 15:09:17 -0700627 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400628 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700629 // request id access to RADIUS
630 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700631
Ray Milkey967776a2015-10-07 14:37:17 -0700632 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100633 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800634 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700635
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100636 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000637 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700638 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000639 if (stateMachine.state() == StateMachine.STATE_PENDING) {
640 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
641 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700642 stateMachine.requestAccess();
643 break;
Ari Saha89831742015-06-26 10:31:48 -0700644 case EAP.ATTR_MD5:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400645 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700646 // verify if the EAP identifier corresponds to the
647 // challenge identifier from the client state
648 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700649 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700650 //send the RADIUS challenge response
Ray Milkey967776a2015-10-07 14:37:17 -0700651 radiusPayload =
652 getRadiusPayload(stateMachine,
653 stateMachine.identifier(),
654 eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100655 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700656
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800657 if (stateMachine.challengeState() != null) {
658 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
659 stateMachine.challengeState());
660 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800661 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100662 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000663 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700664 }
665 break;
666 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400667 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700668 // request id access to RADIUS
Ray Milkey967776a2015-10-07 14:37:17 -0700669 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100670 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700671
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800672 if (stateMachine.challengeState() != null) {
673 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
674 stateMachine.challengeState());
675 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700676 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700677
Jonathan Hart092dfb22015-11-16 23:05:21 -0800678 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100679 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000680 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700681
Ray Milkeyf3790b82015-10-21 16:28:08 -0700682 if (stateMachine.state() != StateMachine.STATE_PENDING) {
683 stateMachine.requestAccess();
684 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700685
Ari Saha89831742015-06-26 10:31:48 -0700686 break;
687 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400688 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700689 return;
690 }
691 break;
692 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400693 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700694 }
Shubham Sharmac155ef82019-07-11 12:12:41 +0000695 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
696 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700697 }
Ray Milkey967776a2015-10-07 14:37:17 -0700698 }
699
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100700 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700701 * Delegate allowing the StateMachine to notify us of events.
702 */
703 private class InternalStateMachineDelegate implements StateMachineDelegate {
704
705 @Override
706 public void notify(AuthenticationEvent authenticationEvent) {
707 log.info("Auth event {} for {}",
708 authenticationEvent.type(), authenticationEvent.subject());
709 post(authenticationEvent);
710 }
711 }
712
713 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100714 * Configuration Listener, handles change in configuration.
715 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700716 private class InternalConfigListener implements NetworkConfigListener {
717
718 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800719 * Reconfigures the AAA application according to the
720 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700721 *
722 * @param cfg configuration object
723 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800724 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400725 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100726
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700727 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800728 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700729 } else {
730 newCfg = cfg;
731 }
732 if (newCfg.nasIp() != null) {
733 nasIpAddress = newCfg.nasIp();
734 }
735 if (newCfg.radiusIp() != null) {
736 radiusIpAddress = newCfg.radiusIp();
737 }
738 if (newCfg.radiusMac() != null) {
739 radiusMacAddress = newCfg.radiusMac();
740 }
741 if (newCfg.nasMac() != null) {
742 nasMacAddress = newCfg.nasMac();
743 }
744 if (newCfg.radiusSecret() != null) {
745 radiusSecret = newCfg.radiusSecret();
746 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100747
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530748 boolean reconfigureCustomizer = false;
749 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
750 customizer = newCfg.radiusPktCustomizer();
751 configurePacketCustomizer();
752 reconfigureCustomizer = true;
753 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100754
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530755 if (radiusConnectionType == null
756 || reconfigureCustomizer
757 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
758 radiusConnectionType = newCfg.radiusConnectionType();
759 if (impl != null) {
760 impl.withdrawIntercepts();
761 impl.clearLocalState();
762 }
763 configureRadiusCommunication();
764 impl.initializeLocalState(newCfg);
765 impl.requestIntercepts();
766 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100767 impl.clearLocalState();
768 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -0700769 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700770 }
771
772 @Override
773 public void event(NetworkConfigEvent event) {
774
775 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
776 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -0800777 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700778
Jonathan Hart092dfb22015-11-16 23:05:21 -0800779 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700780 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100781
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400782 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700783 }
784 }
785 }
Amit Ghoshf739be52017-09-21 15:49:37 +0100786
787 private class InternalDeviceListener implements DeviceListener {
788 @Override
789 public void event(DeviceEvent event) {
790
791 switch (event.type()) {
792 case PORT_REMOVED:
793 DeviceId devId = event.subject().id();
794 PortNumber portNumber = event.port().number();
795 String sessionId = devId.toString() + portNumber.toString();
796
797 Map<String, StateMachine> sessionIdMap = StateMachine.sessionIdMap();
798 StateMachine removed = sessionIdMap.remove(sessionId);
799 if (removed != null) {
800 StateMachine.deleteStateMachineMapping(removed);
801 }
802
803 break;
804 default:
805 return;
806 }
807 }
808 }
kartikey dubeye1545422019-05-22 12:53:45 +0000809 private class AuthenticationStatisticsEventPublisher implements Runnable {
810 private final Logger log = getLogger(getClass());
811 public void run() {
812 log.info("Notifying AuthenticationStatisticsEvent");
813 aaaStatisticsManager.calculatePacketRoundtripTime();
814 log.debug("AcceptResponsesRx---" + aaaStatisticsManager.getAaaStats().getAcceptResponsesRx());
815 log.debug("AccessRequestsTx---" + aaaStatisticsManager.getAaaStats().getAccessRequestsTx());
816 log.debug("ChallengeResponsesRx---" + aaaStatisticsManager.getAaaStats().getChallengeResponsesRx());
817 log.debug("DroppedResponsesRx---" + aaaStatisticsManager.getAaaStats().getDroppedResponsesRx());
818 log.debug("InvalidValidatorsRx---" + aaaStatisticsManager.getAaaStats().getInvalidValidatorsRx());
819 log.debug("MalformedResponsesRx---" + aaaStatisticsManager.getAaaStats().getMalformedResponsesRx());
820 log.debug("PendingRequests---" + aaaStatisticsManager.getAaaStats().getPendingRequests());
821 log.debug("RejectResponsesRx---" + aaaStatisticsManager.getAaaStats().getRejectResponsesRx());
822 log.debug("RequestReTx---" + aaaStatisticsManager.getAaaStats().getRequestReTx());
823 log.debug("RequestRttMilis---" + aaaStatisticsManager.getAaaStats().getRequestRttMilis());
824 log.debug("UnknownServerRx---" + aaaStatisticsManager.getAaaStats().getUnknownServerRx());
825 log.debug("UnknownTypeRx---" + aaaStatisticsManager.getAaaStats().getUnknownTypeRx());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000826 log.debug("EapolLogoffRx---" + aaaStatisticsManager.getAaaStats().getEapolLogoffRx());
827 log.debug("EapolAuthSuccessTrans---" + aaaStatisticsManager.getAaaStats().getEapolAuthSuccessTrans());
828 log.debug("EapolAuthFailureTrans---" +
829 aaaStatisticsManager.getAaaStats().getEapolAuthFailureTrans());
830 log.debug("EapolStartReqTrans---" +
831 aaaStatisticsManager.getAaaStats().getEapolStartReqTrans());
832 log.debug("EapolTransRespNotNak---" +
833 aaaStatisticsManager.getAaaStats().getEapolTransRespNotNak());
834 log.debug("EapPktTxauthChooseEap---" +
835 aaaStatisticsManager.getAaaStats().getEapPktTxauthChooseEap());
836 log.debug("EapolResIdentityMsgTrans---" +
837 aaaStatisticsManager.getAaaStats().getEapolResIdentityMsgTrans());
kartikey dubeye1545422019-05-22 12:53:45 +0000838 aaaStatisticsManager.getStatsDelegate().
839 notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
840 aaaStatisticsManager.getAaaStats()));
841 }
842 }
Ari Saha89831742015-06-26 10:31:48 -0700843}