blob: 1323e5f0531383d7095a90073169a57575c4ad92 [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;
Carmelo Cascone58b53292019-09-30 12:35:31 -070030import org.osgi.service.component.annotations.Component;
31import org.osgi.service.component.annotations.Deactivate;
32import org.osgi.service.component.annotations.Reference;
33import org.osgi.service.component.annotations.ReferenceCardinality;
Jonathan Hart4731dd92018-05-02 17:30:05 -070034import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070035import org.onlab.packet.EAP;
36import org.onlab.packet.EAPOL;
37import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070038import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070039import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070040import org.onlab.packet.RADIUS;
41import org.onlab.packet.RADIUSAttribute;
kartikey dubeye1545422019-05-22 12:53:45 +000042import org.onlab.util.Tools;
43import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070044import org.onosproject.core.ApplicationId;
45import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070046import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010047import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070048import org.onosproject.net.ConnectPoint;
49import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070050import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070051import org.onosproject.net.config.ConfigFactory;
52import org.onosproject.net.config.NetworkConfigEvent;
53import org.onosproject.net.config.NetworkConfigListener;
54import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010055import org.onosproject.net.device.DeviceEvent;
56import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010057import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070058import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070059import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070060import org.onosproject.net.packet.DefaultOutboundPacket;
61import org.onosproject.net.packet.InboundPacket;
62import org.onosproject.net.packet.OutboundPacket;
63import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070064import org.onosproject.net.packet.PacketProcessor;
65import org.onosproject.net.packet.PacketService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070066import org.opencord.aaa.AaaConfig;
67import org.opencord.aaa.AuthenticationEvent;
68import org.opencord.aaa.AuthenticationEventListener;
69import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000070import org.opencord.aaa.AuthenticationStatisticsEvent;
71import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070072import org.opencord.aaa.RadiusCommunicator;
73import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000074import org.opencord.sadis.BaseInformationService;
75import org.opencord.sadis.SadisService;
76import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000077import org.osgi.service.component.ComponentContext;
Carmelo Cascone58b53292019-09-30 12:35:31 -070078import org.osgi.service.component.annotations.Modified;
79import org.osgi.service.component.annotations.Activate;
Ari Saha89831742015-06-26 10:31:48 -070080import org.slf4j.Logger;
kartikey dubeye1545422019-05-22 12:53:45 +000081import com.google.common.base.Strings;
Ari Saha89831742015-06-26 10:31:48 -070082
kartikey dubeye1545422019-05-22 12:53:45 +000083import java.util.concurrent.Executors;
84import java.util.concurrent.ScheduledExecutorService;
85import java.util.concurrent.ScheduledFuture;
86import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000087
Carmelo Cascone58b53292019-09-30 12:35:31 -070088import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_EVENT;
89import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_EVENT_DEFAULT;
90
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000091import javax.crypto.Mac;
92import javax.crypto.spec.SecretKeySpec;
Ari Saha89831742015-06-26 10:31:48 -070093/**
Jonathan Harta46dddf2015-06-30 15:31:20 -070094 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -070095 */
Carmelo Cascone58b53292019-09-30 12:35:31 -070096@Component(immediate = true, property = {
97 STATISTICS_GENERATION_EVENT + ":Integer=" + STATISTICS_GENERATION_EVENT_DEFAULT,
98})
Jonathan Hart5db44532018-07-12 18:13:54 -070099public class AaaManager
100 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
101 implements AuthenticationService {
102
Charles Chandf7ff862017-01-20 11:22:05 -0800103 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -0700104
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700105 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700106
Carmelo Cascone58b53292019-09-30 12:35:31 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700108 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700109
Carmelo Cascone58b53292019-09-30 12:35:31 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700111 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700112
Carmelo Cascone58b53292019-09-30 12:35:31 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700114 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700115
Carmelo Cascone58b53292019-09-30 12:35:31 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100117 protected DeviceService deviceService;
118
Carmelo Cascone58b53292019-09-30 12:35:31 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000120 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100121
Carmelo Cascone58b53292019-09-30 12:35:31 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100123 protected MastershipService mastershipService;
124
Carmelo Cascone58b53292019-09-30 12:35:31 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000126 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000127
Carmelo Cascone58b53292019-09-30 12:35:31 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000129 protected ComponentConfigService cfgService;
130
131 protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
132 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100133 private final DeviceListener deviceListener = new InternalDeviceListener();
134
Carmelo Cascone58b53292019-09-30 12:35:31 -0700135 /** Statistics generation interval. */
136 private int statisticsGenerationEvent = STATISTICS_GENERATION_EVENT_DEFAULT;
kartikey dubeye1545422019-05-22 12:53:45 +0000137
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
Shubham Sharma1e43c562019-06-19 14:18:12 +0000162 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
163 protected int cleanupTimerTimeOutInMins;
164
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100165 // Setup specific customization/attributes on the RADIUS packets
166 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700167
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100168 // packet customizer to use
169 private String customizer;
170
171 // Type of connection to use to communicate with Radius server, options are
172 // "socket" or "packet_out"
173 private String radiusConnectionType;
174
Jonathan Hart5db44532018-07-12 18:13:54 -0700175 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100176 // server, socket based or packet_out based
177 RadiusCommunicator impl = null;
178
179 // latest configuration
180 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700181
kartikey dubeye1545422019-05-22 12:53:45 +0000182 ScheduledFuture<?> scheduledFuture;
183
184 ScheduledExecutorService executor;
185 String configuredAaaServerAddress;
186 HashSet<Byte> outPacketSet = new HashSet<Byte>();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700187 // Configuration properties factory
188 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800189 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
190 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700191 "AAA") {
192 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800193 public AaaConfig createConfig() {
194 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700195 }
196 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700197
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700198 // Listener for config changes
199 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700200
Jonathan Hart5db44532018-07-12 18:13:54 -0700201 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
202
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700203 /**
204 * Builds an EAPOL packet based on the given parameters.
205 *
206 * @param dstMac destination MAC address
207 * @param srcMac source MAC address
208 * @param vlan vlan identifier
209 * @param eapolType EAPOL type
210 * @param eap EAP payload
211 * @return Ethernet frame
212 */
213 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100214 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700215
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700216 Ethernet eth = new Ethernet();
217 eth.setDestinationMACAddress(dstMac.toBytes());
218 eth.setSourceMACAddress(srcMac.toBytes());
219 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
220 if (vlan != Ethernet.VLAN_UNTAGGED) {
221 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100222 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700223 }
224 //eapol header
225 EAPOL eapol = new EAPOL();
226 eapol.setEapolType(eapolType);
227 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700228
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700229 //eap part
230 eapol.setPayload(eap);
231
232 eth.setPayload(eapol);
233 eth.setPad(true);
234 return eth;
235 }
Ari Saha89831742015-06-26 10:31:48 -0700236
Ari Saha89831742015-06-26 10:31:48 -0700237 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000238 public void activate(ComponentContext context) {
Charles Chandf7ff862017-01-20 11:22:05 -0800239 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart5db44532018-07-12 18:13:54 -0700240 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400241 netCfgService.addListener(cfgListener);
242 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000243 cfgService.registerProperties(getClass());
244 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000245 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530246 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800247 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400248 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530249 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700250 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700251 packetService.addProcessor(processor, PacketProcessor.director(2));
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700252 StateMachine.initializeMaps();
Jonathan Hart5db44532018-07-12 18:13:54 -0700253 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000254 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
255 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100256 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100257 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100258 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000259 getConfiguredAaaServerAddress();
260 authenticationStatisticsPublisher =
261 new AuthenticationStatisticsEventPublisher();
262 executor = Executors.newScheduledThreadPool(1);
263 scheduledFuture = executor.scheduleAtFixedRate(authenticationStatisticsPublisher,
264 0, statisticsGenerationEvent, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100265
Jian Li13c67162015-12-09 13:20:34 -0800266 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700267 }
268
269 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000270 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100271 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700272 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530273 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000274 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700275 StateMachine.unsetDelegate(delegate);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530276 StateMachine.destroyMaps();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100277 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100278 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700279 eventDispatcher.removeSink(AuthenticationEvent.class);
kartikey dubeye1545422019-05-22 12:53:45 +0000280 scheduledFuture.cancel(true);
281 executor.shutdown();
Jian Li13c67162015-12-09 13:20:34 -0800282 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700283 }
284
kartikey dubeye1545422019-05-22 12:53:45 +0000285 @Modified
286 public void modified(ComponentContext context) {
287 Dictionary<?, ?> properties = context.getProperties();
Carmelo Cascone58b53292019-09-30 12:35:31 -0700288 String s = Tools.get(properties, STATISTICS_GENERATION_EVENT);
289 statisticsGenerationEvent = Strings.isNullOrEmpty(s)
290 ? STATISTICS_GENERATION_EVENT_DEFAULT : Integer.parseInt(s.trim());
kartikey dubeye1545422019-05-22 12:53:45 +0000291 }
292
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000293 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530294 if (radiusConnectionType.toLowerCase().equals("socket")) {
295 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
296 } else {
297 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
298 deviceService, subsService, pktCustomizer, this);
299 }
300 }
301
302 private void configurePacketCustomizer() {
303 switch (customizer.toLowerCase()) {
304 case "sample":
305 pktCustomizer = new SamplePacketCustomizer(customInfo);
306 log.info("Created SamplePacketCustomizer");
307 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800308 case "att":
309 pktCustomizer = new AttPacketCustomizer(customInfo);
310 log.info("Created AttPacketCustomizer");
311 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530312 default:
313 pktCustomizer = new PacketCustomizer(customInfo);
314 log.info("Created default PacketCustomizer");
315 break;
316 }
317 }
318
kartikey dubeye1545422019-05-22 12:53:45 +0000319 private void getConfiguredAaaServerAddress() {
320 try {
321 InetAddress address;
322 if (newCfg.radiusHostName() != null) {
323 address = InetAddress.getByName(newCfg.radiusHostName());
324 } else {
325 address = newCfg.radiusIp();
326 }
327
328 configuredAaaServerAddress = address.getHostAddress();
329 } catch (UnknownHostException uhe) {
330 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
331 }
332 }
333
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000334 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
335 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000336 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
337 }
338 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000339
340 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
341 byte[] newHash = new byte[16];
342 Arrays.fill(newHash, (byte) 0);
343 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
344 byte[] authenticator = radiusPacket.getAuthenticator();
345 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
346 radiusPacket.setAuthenticator(requestAuthenticator);
347 // Calculate the MD5 HMAC based on the message
348 try {
349 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
350 Mac mac = Mac.getInstance("HmacMD5");
351 mac.init(keySpec);
352 newHash = mac.doFinal(radiusPacket.serialize());
353 } catch (Exception e) {
354 log.error("Failed to generate message authenticator: {}", e.getMessage());
355 }
356 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
357 radiusPacket.setAuthenticator(authenticator);
358 // Compare the calculated Message-Authenticator with the one in the message
359 return Arrays.equals(newHash, messageAuthenticator);
360 }
kartikey dubeye1545422019-05-22 12:53:45 +0000361 public void checkForPacketFromUnknownServer(String hostAddress) {
362 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000363 getConfiguredAaaServerAddress();
364 if (!hostAddress.equals(configuredAaaServerAddress)) {
365 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
366 }
kartikey dubeye1545422019-05-22 12:53:45 +0000367 }
368 }
369
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100370 /**
371 * Send RADIUS packet to the RADIUS server.
372 *
373 * @param radiusPacket RADIUS packet to be sent to server.
374 * @param inPkt Incoming EAPOL packet
375 */
376 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000377 outPacketSet.add(radiusPacket.getIdentifier());
378 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
379 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100380 impl.sendRadiusPacket(radiusPacket, inPkt);
381 }
Ray Milkey967776a2015-10-07 14:37:17 -0700382
Shubham Sharma1e43c562019-06-19 14:18:12 +0000383 /**
384 * For scheduling the timer required for cleaning up StateMachine
385 * when no response
386 * from RADIUS SERVER.
387 *
388 * @param sessionId SessionId of the current session
389 * @param stateMachine StateMachine for the id
390 */
391 public void scheduleStateMachineCleanupTimer(String sessionId, StateMachine stateMachine) {
392 StateMachine.CleanupTimerTask cleanupTask = stateMachine.new CleanupTimerTask(sessionId, this);
393 ScheduledFuture<?> cleanupTimer = executor.schedule(cleanupTask, cleanupTimerTimeOutInMins, TimeUnit.MINUTES);
394 stateMachine.setCleanupTimer(cleanupTimer);
395
396 }
397
398 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100399 * Handles RADIUS packets.
400 *
401 * @param radiusPacket RADIUS packet coming from the RADIUS server.
402 * @throws StateMachineException if an illegal state transition is triggered
Jonathan Hart4731dd92018-05-02 17:30:05 -0700403 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100404 */
Jonathan Hart4731dd92018-05-02 17:30:05 -0700405 public void handleRadiusPacket(RADIUS radiusPacket)
406 throws StateMachineException, DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700407 if (log.isTraceEnabled()) {
408 log.trace("Received RADIUS packet {}", radiusPacket);
409 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100410 StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
411 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700412 log.error("Invalid packet identifier {}, could not find corresponding "
413 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000414 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
415 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100416 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700417 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100418 EAP eapPayload;
419 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000420 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
kartikey dubeye1545422019-05-22 12:53:45 +0000421 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
422 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
423 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
424 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100425 switch (radiusPacket.getCode()) {
426 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400427 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100428 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
429 byte[] challengeState = null;
430 if (radiusAttrState != null) {
431 challengeState = radiusAttrState.getValue();
432 }
433 eapPayload = radiusPacket.decapsulateMessage();
434 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
435 eth = buildEapolResponse(stateMachine.supplicantAddress(),
436 MacAddress.valueOf(nasMacAddress),
437 stateMachine.vlanId(),
438 EAPOL.EAPOL_PACKET,
439 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400440 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000441 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000442 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100443 break;
444 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400445 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100446 //send an EAPOL - Success to the supplicant.
447 byte[] eapMessageSuccess =
448 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700449 eapPayload = EAP.deserializer().deserialize(
450 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100451 eth = buildEapolResponse(stateMachine.supplicantAddress(),
452 MacAddress.valueOf(nasMacAddress),
453 stateMachine.vlanId(),
454 EAPOL.EAPOL_PACKET,
455 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400456 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000457 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
458 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100459
460 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000461 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100462 break;
463 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400464 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100465 //send an EAPOL - Failure to the supplicant.
466 byte[] eapMessageFailure;
467 eapPayload = new EAP();
468 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
469 if (radiusAttrEap == null) {
470 eapPayload.setCode(EAP.FAILURE);
471 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
472 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
473 } else {
474 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700475 eapPayload = EAP.deserializer().deserialize(
476 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100477 }
478 eth = buildEapolResponse(stateMachine.supplicantAddress(),
479 MacAddress.valueOf(nasMacAddress),
480 stateMachine.vlanId(),
481 EAPOL.EAPOL_PACKET,
482 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400483 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000484 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
485 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
486
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100487 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000488 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100489 break;
490 default:
491 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000492 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100493 }
kartikey dubeye1545422019-05-22 12:53:45 +0000494 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700495 }
496
Ray Milkey967776a2015-10-07 14:37:17 -0700497 /**
498 * Send the ethernet packet to the supplicant.
499 *
500 * @param ethernetPkt the ethernet packet
501 * @param connectPoint the connect point to send out
502 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000503 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700504 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
505 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
506 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000507 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
508 EAP eapPkt = (EAP) eap.getPayload();
Saurav Das987441a2018-09-18 16:33:47 -0700509 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700510 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
511 eap, ethernetPkt, connectPoint);
512 }
Ray Milkey967776a2015-10-07 14:37:17 -0700513 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000514 if (isChallengeResponse) {
515 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
516 }
Ray Milkey967776a2015-10-07 14:37:17 -0700517 }
518
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400519 @Override
520 public String toString() {
521 return ToStringBuilder.reflectionToString(this);
522 }
523
Ari Saha89831742015-06-26 10:31:48 -0700524 // our handler defined as a private inner class
525
526 /**
527 * Packet processor responsible for forwarding packets along their paths.
528 */
529 private class ReactivePacketProcessor implements PacketProcessor {
530 @Override
531 public void process(PacketContext context) {
532
533 // Extract the original Ethernet frame from the packet information
534 InboundPacket pkt = context.inPacket();
535 Ethernet ethPkt = pkt.parsed();
536 if (ethPkt == null) {
537 return;
538 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100539
Ray Milkeyf51eba22015-09-25 10:24:23 -0700540 try {
541 // identify if incoming packet comes from supplicant (EAP) or RADIUS
542 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
543 case EAPOL:
544 handleSupplicantPacket(context.inPacket());
545 break;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700546 default:
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100547 // any other packets let the specific implementation handle
548 impl.handlePacketFromServer(context);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700549 }
Ray Milkey967776a2015-10-07 14:37:17 -0700550 } catch (StateMachineException e) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100551 log.warn("Unable to process packet:", e);
Ari Saha89831742015-06-26 10:31:48 -0700552 }
553 }
554
Ray Milkey9eb293f2015-09-30 15:09:17 -0700555 /**
556 * Creates and initializes common fields of a RADIUS packet.
557 *
Ray Milkey967776a2015-10-07 14:37:17 -0700558 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700559 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700560 * @return RADIUS packet
561 */
Ray Milkey967776a2015-10-07 14:37:17 -0700562 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700563 RADIUS radiusPayload =
564 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
565 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700566
567 // set Request Authenticator in StateMachine
568 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
569
Ray Milkey9eb293f2015-09-30 15:09:17 -0700570 radiusPayload.setIdentifier(identifier);
571 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700572 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700573
574 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800575 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700576
577 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700578
579 return radiusPayload;
580 }
Ari Saha89831742015-06-26 10:31:48 -0700581
582 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700583 * Handles PAE packets (supplicant).
584 *
585 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700586 */
Ray Milkeyf51eba22015-09-25 10:24:23 -0700587 private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700588 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700589 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800590 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700591
Jonathan Harta46dddf2015-06-30 15:31:20 -0700592 DeviceId deviceId = inPacket.receivedFrom().deviceId();
593 PortNumber portNumber = inPacket.receivedFrom().port();
Ari Saha89831742015-06-26 10:31:48 -0700594 String sessionId = deviceId.toString() + portNumber.toString();
Saurav Das987441a2018-09-18 16:33:47 -0700595 EAPOL eapol = (EAPOL) ethPkt.getPayload();
596 if (log.isTraceEnabled()) {
597 log.trace("Received EAPOL packet {} in enclosing packet {} from "
598 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
599 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100600 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700601
Saurav Das987441a2018-09-18 16:33:47 -0700602 StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
603 if (stateMachine == null) {
604 log.debug("Creating new state machine for sessionId: {} for "
605 + "dev/port: {}/{}", sessionId, deviceId, portNumber);
606 stateMachine = new StateMachine(sessionId);
607 } else {
608 log.debug("Using existing state-machine for sessionId: {}", sessionId);
609 }
610
Ari Saha89831742015-06-26 10:31:48 -0700611 switch (eapol.getEapolType()) {
612 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400613 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700614 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Shubham Sharma1e43c562019-06-19 14:18:12 +0000615 if (stateMachine.getCleanupTimer() == null) {
616 scheduleStateMachineCleanupTimer(sessionId, stateMachine);
617 }
Jonathan Hart5db44532018-07-12 18:13:54 -0700618 stateMachine.start();
Shubham Sharma1f193582019-07-11 12:12:41 +0000619 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700620 //send an EAP Request/Identify to the supplicant
621 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100622 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
623 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
624 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800625 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700626 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100627 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400628
Jonathan Hart092dfb22015-11-16 23:05:21 -0800629 stateMachine.setSupplicantAddress(srcMac);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700630 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400631 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000632 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Ari Saha89831742015-06-26 10:31:48 -0700633
634 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800635 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400636 log.debug("EAP packet: EAPOL_LOGOFF");
Ray Milkeyb34b4962016-01-04 10:24:43 -0800637 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
638 stateMachine.logoff();
Shubham Sharma1f193582019-07-11 12:12:41 +0000639 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800640 }
641
642 break;
Ari Saha89831742015-06-26 10:31:48 -0700643 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700644 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700645 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700646 EAP eapPacket = (EAP) eapol.getPayload();
647
648 byte dataType = eapPacket.getDataType();
649 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700650
Ray Milkey9eb293f2015-09-30 15:09:17 -0700651 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400652 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharma1e43c562019-06-19 14:18:12 +0000653 //Setting the time of this response from RG, only when its not a re-transmission.
654 if (stateMachine.getLastPacketReceivedTime() == 0) {
655 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
656 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700657 // request id access to RADIUS
658 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700659
Ray Milkey967776a2015-10-07 14:37:17 -0700660 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100661 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800662 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700663
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100664 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000665 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000666 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700667 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000668 if (stateMachine.state() == StateMachine.STATE_PENDING) {
669 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
670 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700671 stateMachine.requestAccess();
672 break;
Ari Saha89831742015-06-26 10:31:48 -0700673 case EAP.ATTR_MD5:
Shubham Sharma1e43c562019-06-19 14:18:12 +0000674 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400675 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700676 // verify if the EAP identifier corresponds to the
677 // challenge identifier from the client state
678 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700679 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700680 //send the RADIUS challenge response
Ray Milkey967776a2015-10-07 14:37:17 -0700681 radiusPayload =
682 getRadiusPayload(stateMachine,
683 stateMachine.identifier(),
684 eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100685 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700686
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800687 if (stateMachine.challengeState() != null) {
688 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
689 stateMachine.challengeState());
690 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800691 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100692 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000693 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000694 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700695 }
696 break;
697 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400698 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700699 // request id access to RADIUS
Ray Milkey967776a2015-10-07 14:37:17 -0700700 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100701 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700702
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800703 if (stateMachine.challengeState() != null) {
704 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
705 stateMachine.challengeState());
706 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700707 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700708
Jonathan Hart092dfb22015-11-16 23:05:21 -0800709 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100710 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000711 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000712 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700713
Ray Milkeyf3790b82015-10-21 16:28:08 -0700714 if (stateMachine.state() != StateMachine.STATE_PENDING) {
715 stateMachine.requestAccess();
716 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700717
Ari Saha89831742015-06-26 10:31:48 -0700718 break;
719 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400720 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700721 return;
722 }
723 break;
724 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400725 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700726 }
Shubham Sharma1f193582019-07-11 12:12:41 +0000727 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
728 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700729 }
Ray Milkey967776a2015-10-07 14:37:17 -0700730 }
731
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100732 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700733 * Delegate allowing the StateMachine to notify us of events.
734 */
735 private class InternalStateMachineDelegate implements StateMachineDelegate {
736
737 @Override
738 public void notify(AuthenticationEvent authenticationEvent) {
739 log.info("Auth event {} for {}",
740 authenticationEvent.type(), authenticationEvent.subject());
741 post(authenticationEvent);
742 }
743 }
744
745 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100746 * Configuration Listener, handles change in configuration.
747 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700748 private class InternalConfigListener implements NetworkConfigListener {
749
750 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800751 * Reconfigures the AAA application according to the
752 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700753 *
754 * @param cfg configuration object
755 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800756 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400757 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100758
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700759 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800760 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700761 } else {
762 newCfg = cfg;
763 }
764 if (newCfg.nasIp() != null) {
765 nasIpAddress = newCfg.nasIp();
766 }
767 if (newCfg.radiusIp() != null) {
768 radiusIpAddress = newCfg.radiusIp();
769 }
770 if (newCfg.radiusMac() != null) {
771 radiusMacAddress = newCfg.radiusMac();
772 }
773 if (newCfg.nasMac() != null) {
774 nasMacAddress = newCfg.nasMac();
775 }
776 if (newCfg.radiusSecret() != null) {
777 radiusSecret = newCfg.radiusSecret();
778 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100779
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530780 boolean reconfigureCustomizer = false;
781 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
782 customizer = newCfg.radiusPktCustomizer();
783 configurePacketCustomizer();
784 reconfigureCustomizer = true;
785 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100786
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530787 if (radiusConnectionType == null
788 || reconfigureCustomizer
789 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
790 radiusConnectionType = newCfg.radiusConnectionType();
791 if (impl != null) {
792 impl.withdrawIntercepts();
793 impl.clearLocalState();
794 }
795 configureRadiusCommunication();
796 impl.initializeLocalState(newCfg);
797 impl.requestIntercepts();
798 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100799 impl.clearLocalState();
800 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -0700801 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700802 }
803
804 @Override
805 public void event(NetworkConfigEvent event) {
806
807 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
808 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -0800809 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700810
Jonathan Hart092dfb22015-11-16 23:05:21 -0800811 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700812 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100813
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400814 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700815 }
816 }
817 }
Amit Ghoshf739be52017-09-21 15:49:37 +0100818
819 private class InternalDeviceListener implements DeviceListener {
820 @Override
821 public void event(DeviceEvent event) {
822
823 switch (event.type()) {
824 case PORT_REMOVED:
825 DeviceId devId = event.subject().id();
826 PortNumber portNumber = event.port().number();
827 String sessionId = devId.toString() + portNumber.toString();
828
829 Map<String, StateMachine> sessionIdMap = StateMachine.sessionIdMap();
830 StateMachine removed = sessionIdMap.remove(sessionId);
831 if (removed != null) {
832 StateMachine.deleteStateMachineMapping(removed);
833 }
834
835 break;
836 default:
837 return;
838 }
839 }
840 }
kartikey dubeye1545422019-05-22 12:53:45 +0000841 private class AuthenticationStatisticsEventPublisher implements Runnable {
842 private final Logger log = getLogger(getClass());
843 public void run() {
844 log.info("Notifying AuthenticationStatisticsEvent");
845 aaaStatisticsManager.calculatePacketRoundtripTime();
846 log.debug("AcceptResponsesRx---" + aaaStatisticsManager.getAaaStats().getAcceptResponsesRx());
847 log.debug("AccessRequestsTx---" + aaaStatisticsManager.getAaaStats().getAccessRequestsTx());
848 log.debug("ChallengeResponsesRx---" + aaaStatisticsManager.getAaaStats().getChallengeResponsesRx());
849 log.debug("DroppedResponsesRx---" + aaaStatisticsManager.getAaaStats().getDroppedResponsesRx());
850 log.debug("InvalidValidatorsRx---" + aaaStatisticsManager.getAaaStats().getInvalidValidatorsRx());
851 log.debug("MalformedResponsesRx---" + aaaStatisticsManager.getAaaStats().getMalformedResponsesRx());
852 log.debug("PendingRequests---" + aaaStatisticsManager.getAaaStats().getPendingRequests());
853 log.debug("RejectResponsesRx---" + aaaStatisticsManager.getAaaStats().getRejectResponsesRx());
854 log.debug("RequestReTx---" + aaaStatisticsManager.getAaaStats().getRequestReTx());
855 log.debug("RequestRttMilis---" + aaaStatisticsManager.getAaaStats().getRequestRttMilis());
856 log.debug("UnknownServerRx---" + aaaStatisticsManager.getAaaStats().getUnknownServerRx());
857 log.debug("UnknownTypeRx---" + aaaStatisticsManager.getAaaStats().getUnknownTypeRx());
Shubham Sharma1e43c562019-06-19 14:18:12 +0000858 log.debug("TimedOutPackets----" + aaaStatisticsManager.getAaaStats().getTimedOutPackets());
Shubham Sharma1f193582019-07-11 12:12:41 +0000859 log.debug("EapolLogoffRx---" + aaaStatisticsManager.getAaaStats().getEapolLogoffRx());
860 log.debug("EapolAuthSuccessTrans---" + aaaStatisticsManager.getAaaStats().getEapolAuthSuccessTrans());
861 log.debug("EapolAuthFailureTrans---" +
862 aaaStatisticsManager.getAaaStats().getEapolAuthFailureTrans());
863 log.debug("EapolStartReqTrans---" +
864 aaaStatisticsManager.getAaaStats().getEapolStartReqTrans());
865 log.debug("EapolTransRespNotNak---" +
866 aaaStatisticsManager.getAaaStats().getEapolTransRespNotNak());
867 log.debug("EapPktTxauthChooseEap---" +
868 aaaStatisticsManager.getAaaStats().getEapPktTxauthChooseEap());
869 log.debug("EapolResIdentityMsgTrans---" +
870 aaaStatisticsManager.getAaaStats().getEapolResIdentityMsgTrans());
kartikey dubeye1545422019-05-22 12:53:45 +0000871 aaaStatisticsManager.getStatsDelegate().
872 notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
873 aaaStatisticsManager.getAaaStats()));
874 }
875 }
Ari Saha89831742015-06-26 10:31:48 -0700876}