blob: 85b1ce25a75d891e3ea129482bf047ed30e2c654 [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
Shubham Sharma4900ce62019-06-19 14:18:50 +000018import com.google.common.base.Strings;
Jonathan Hart612651f2019-11-25 09:21:43 -080019import com.google.common.collect.Maps;
Girish Kumar064084c2020-02-04 08:32:46 +000020import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
21import static org.slf4j.LoggerFactory.getLogger;
22
23import com.google.common.collect.Sets;
24import java.net.InetAddress;
25import java.net.UnknownHostException;
26import java.nio.ByteBuffer;
27import java.util.Dictionary;
28import java.util.HashSet;
29import java.util.Arrays;
30import java.util.List;
31import java.util.Set;
32import java.util.Map.Entry;
33
Jonathan Hart932bedc2018-07-12 13:46:09 -070034import org.apache.commons.lang3.builder.ToStringBuilder;
Jonathan Hart4731dd92018-05-02 17:30:05 -070035import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070036import org.onlab.packet.EAP;
37import org.onlab.packet.EAPOL;
38import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070039import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070040import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070041import org.onlab.packet.RADIUS;
42import org.onlab.packet.RADIUSAttribute;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080043import org.onlab.util.KryoNamespace;
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;
Jonathan Hartc41227c2020-01-28 16:56:49 -080068import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080069import org.onosproject.store.service.ConsistentMap;
70import org.onosproject.store.service.MapEvent;
71import org.onosproject.store.service.MapEventListener;
72import org.onosproject.store.service.Serializer;
73import org.onosproject.store.service.StorageService;
74import org.onosproject.store.service.Versioned;
Matteo Scandolocf847b82019-04-26 15:00:00 -070075import org.opencord.aaa.AaaConfig;
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +000076import org.opencord.aaa.AaaMachineStatisticsEvent;
77import org.opencord.aaa.AaaMachineStatisticsService;
78import org.opencord.aaa.AaaSupplicantMachineStats;
Matteo Scandolocf847b82019-04-26 15:00:00 -070079import org.opencord.aaa.AuthenticationEvent;
80import org.opencord.aaa.AuthenticationEventListener;
Jonathan Hart612651f2019-11-25 09:21:43 -080081import org.opencord.aaa.AuthenticationRecord;
Matteo Scandolocf847b82019-04-26 15:00:00 -070082import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000083import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070084import org.opencord.aaa.RadiusCommunicator;
Shubham Sharma4900ce62019-06-19 14:18:50 +000085import org.opencord.aaa.RadiusOperationalStatusEvent;
86import org.opencord.aaa.RadiusOperationalStatusService;
87import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
Matteo Scandolocf847b82019-04-26 15:00:00 -070088import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000089import org.opencord.sadis.BaseInformationService;
90import org.opencord.sadis.SadisService;
91import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000092import org.osgi.service.component.ComponentContext;
Carmelo Cascone58b53292019-09-30 12:35:31 -070093import org.osgi.service.component.annotations.Activate;
Shubham Sharma4900ce62019-06-19 14:18:50 +000094import org.osgi.service.component.annotations.Component;
95import org.osgi.service.component.annotations.Deactivate;
96import org.osgi.service.component.annotations.Modified;
97import org.osgi.service.component.annotations.Reference;
98import org.osgi.service.component.annotations.ReferenceCardinality;
Ari Saha89831742015-06-26 10:31:48 -070099import org.slf4j.Logger;
100
Shubham Sharma4900ce62019-06-19 14:18:50 +0000101import javax.crypto.Mac;
102import javax.crypto.spec.SecretKeySpec;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800103import java.util.Optional;
Jonathan Hart612651f2019-11-25 09:21:43 -0800104import java.util.concurrent.ConcurrentMap;
kartikey dubeye1545422019-05-22 12:53:45 +0000105import java.util.concurrent.Executors;
106import java.util.concurrent.ScheduledExecutorService;
107import java.util.concurrent.ScheduledFuture;
108import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000109
Shubham Sharma4900ce62019-06-19 14:18:50 +0000110import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION;
111import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
112import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT;
113import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
Shubham Sharma4900ce62019-06-19 14:18:50 +0000114import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE;
115import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE_DEFAULT;
Carmelo Cascone58b53292019-09-30 12:35:31 -0700116
Ari Saha89831742015-06-26 10:31:48 -0700117/**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700118 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -0700119 */
Carmelo Cascone58b53292019-09-30 12:35:31 -0700120@Component(immediate = true, property = {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000121 OPERATIONAL_STATUS_SERVER_EVENT_GENERATION + ":Integer=" + OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT,
122 OPERATIONAL_STATUS_SERVER_TIMEOUT + ":Integer=" + OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT,
123 STATUS_SERVER_MODE + ":String=" + STATUS_SERVER_MODE_DEFAULT,
Carmelo Cascone58b53292019-09-30 12:35:31 -0700124})
Jonathan Hart5db44532018-07-12 18:13:54 -0700125public class AaaManager
126 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
127 implements AuthenticationService {
128
Charles Chandf7ff862017-01-20 11:22:05 -0800129 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -0700130
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700131 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700132
Carmelo Cascone58b53292019-09-30 12:35:31 -0700133 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700134 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700135
Carmelo Cascone58b53292019-09-30 12:35:31 -0700136 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800137 protected StorageService storageService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700140 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700141
Carmelo Cascone58b53292019-09-30 12:35:31 -0700142 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700143 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700144
Carmelo Cascone58b53292019-09-30 12:35:31 -0700145 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100146 protected DeviceService deviceService;
147
Carmelo Cascone58b53292019-09-30 12:35:31 -0700148 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000149 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100150
Carmelo Cascone58b53292019-09-30 12:35:31 -0700151 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100152 protected MastershipService mastershipService;
153
Carmelo Cascone58b53292019-09-30 12:35:31 -0700154 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000155 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000156
Carmelo Cascone58b53292019-09-30 12:35:31 -0700157 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000158 protected AaaMachineStatisticsService aaaSupplicantStatsManager;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000161 protected ComponentConfigService cfgService;
162
Shubham Sharma4900ce62019-06-19 14:18:50 +0000163 @Reference(cardinality = ReferenceCardinality.MANDATORY)
164 protected RadiusOperationalStatusService radiusOperationalStatusService;
165
kartikey dubeye1545422019-05-22 12:53:45 +0000166 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100167 private final DeviceListener deviceListener = new InternalDeviceListener();
168
Shubham Sharma4900ce62019-06-19 14:18:50 +0000169 // Properties
Shubham Sharma4900ce62019-06-19 14:18:50 +0000170 private int operationalStatusEventGenerationPeriodInSeconds = OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
171 private int operationalStatusServerTimeoutInSeconds = OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
172 protected String operationalStatusEvaluationMode = STATUS_SERVER_MODE_DEFAULT;
kartikey dubeye1545422019-05-22 12:53:45 +0000173
Jonathan Hart612651f2019-11-25 09:21:43 -0800174 private IdentifierManager idManager;
175
176 private ConcurrentMap<String, StateMachine> stateMachines;
177
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800178 private ConsistentMap<ConnectPoint, AuthenticationRecord> authentications;
179
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700180 // NAS IP address
181 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100182
183 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700184 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100185
186 // Parsed RADIUS server addresses
187 protected InetAddress radiusIpAddress;
188
189 // MAC address of RADIUS server or net hop router
190 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700191
192 // RADIUS server secret
193 protected String radiusSecret;
194
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100195 // bindings
196 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700197
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700198 // our application-specific event handler
199 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700200
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700201 // our unique identifier
202 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700203
Shubham Sharma1e43c562019-06-19 14:18:12 +0000204 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
205 protected int cleanupTimerTimeOutInMins;
206
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100207 // Setup specific customization/attributes on the RADIUS packets
208 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700209
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100210 // packet customizer to use
211 private String customizer;
212
213 // Type of connection to use to communicate with Radius server, options are
214 // "socket" or "packet_out"
215 private String radiusConnectionType;
216
Jonathan Hart5db44532018-07-12 18:13:54 -0700217 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100218 // server, socket based or packet_out based
219 RadiusCommunicator impl = null;
220
221 // latest configuration
222 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700223
Shubham Sharma4900ce62019-06-19 14:18:50 +0000224 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000225 ScheduledExecutorService executor;
226 String configuredAaaServerAddress;
Jonathan Hartc41227c2020-01-28 16:56:49 -0800227 HashSet<Byte> outPacketSet = new HashSet<>();
228 HashSet<Byte> outPacketSupp = new HashSet<>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000229 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
230 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700231 // Configuration properties factory
232 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800233 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
234 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700235 "AAA") {
236 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800237 public AaaConfig createConfig() {
238 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700239 }
240 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700241
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700242 // Listener for config changes
243 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700244
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800245 private final InternalMapEventListener mapListener = new InternalMapEventListener();
246
Jonathan Hart5db44532018-07-12 18:13:54 -0700247 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
248
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700249 /**
250 * Builds an EAPOL packet based on the given parameters.
251 *
252 * @param dstMac destination MAC address
253 * @param srcMac source MAC address
254 * @param vlan vlan identifier
255 * @param eapolType EAPOL type
256 * @param eap EAP payload
257 * @return Ethernet frame
258 */
259 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100260 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700261
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700262 Ethernet eth = new Ethernet();
263 eth.setDestinationMACAddress(dstMac.toBytes());
264 eth.setSourceMACAddress(srcMac.toBytes());
265 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
266 if (vlan != Ethernet.VLAN_UNTAGGED) {
267 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100268 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700269 }
270 //eapol header
271 EAPOL eapol = new EAPOL();
272 eapol.setEapolType(eapolType);
273 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700274
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700275 //eap part
276 eapol.setPayload(eap);
277
278 eth.setPayload(eapol);
279 eth.setPad(true);
280 return eth;
281 }
Ari Saha89831742015-06-26 10:31:48 -0700282
Ari Saha89831742015-06-26 10:31:48 -0700283 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000284 public void activate(ComponentContext context) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800285 idManager = new IdentifierManager();
286 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800287 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800288
289 KryoNamespace authSerializer = KryoNamespace.newBuilder()
Jonathan Hartc41227c2020-01-28 16:56:49 -0800290 .register(KryoNamespaces.API)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800291 .register(AuthenticationRecord.class)
292 .build();
293
294 authentications = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
295 .withApplicationId(appId)
296 .withName("authentications")
297 .withSerializer(Serializer.using(authSerializer))
298 .build();
299 authentications.addListener(mapListener);
300
Jonathan Hart5db44532018-07-12 18:13:54 -0700301 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400302 netCfgService.addListener(cfgListener);
303 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000304 cfgService.registerProperties(getClass());
305 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000306 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530307 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800308 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400309 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530310 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700311 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700312 packetService.addProcessor(processor, PacketProcessor.director(2));
Jonathan Hart5db44532018-07-12 18:13:54 -0700313 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000314 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
315 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100316 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100317 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100318 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000319 getConfiguredAaaServerAddress();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000320 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000321 executor = Executors.newScheduledThreadPool(3);
322
Shubham Sharma4900ce62019-06-19 14:18:50 +0000323 scheduledStatusServerChecker = executor.scheduleAtFixedRate(new ServerStatusChecker(), 0,
324 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100325
Jian Li13c67162015-12-09 13:20:34 -0800326 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700327 }
328
329 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000330 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100331 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700332 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530333 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000334 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700335 StateMachine.unsetDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100336 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100337 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700338 eventDispatcher.removeSink(AuthenticationEvent.class);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000339 scheduledStatusServerChecker.cancel(true);
kartikey dubeye1545422019-05-22 12:53:45 +0000340 executor.shutdown();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800341
342 authentications.removeListener(mapListener);
343
Jian Li13c67162015-12-09 13:20:34 -0800344 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700345 }
kartikey dubeye1545422019-05-22 12:53:45 +0000346 @Modified
347 public void modified(ComponentContext context) {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000348 Dictionary<String, Object> properties = context.getProperties();
349
Jonathan Hartc41227c2020-01-28 16:56:49 -0800350 String s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
Shubham Sharma4900ce62019-06-19 14:18:50 +0000351 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
352 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
353 : Integer.parseInt(s.trim());
354
355 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
356 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
357 : Integer.parseInt(s.trim());
358
359 s = Tools.get(properties, "operationalStatusEvaluationMode");
360 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
361
362 radiusOperationalStatusService
363 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
364 RadiusOperationalStatusEvaluationMode newEvaluationMode =
365 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
366 if (newEvaluationMode != null) {
367 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
368 operationalStatusEvaluationMode = newEvaluationModeString;
369 } else {
370 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
371 }
kartikey dubeye1545422019-05-22 12:53:45 +0000372 }
373
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000374 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530375 if (radiusConnectionType.toLowerCase().equals("socket")) {
376 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
377 } else {
378 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
379 deviceService, subsService, pktCustomizer, this);
380 }
381 }
382
383 private void configurePacketCustomizer() {
384 switch (customizer.toLowerCase()) {
385 case "sample":
386 pktCustomizer = new SamplePacketCustomizer(customInfo);
387 log.info("Created SamplePacketCustomizer");
388 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800389 case "att":
390 pktCustomizer = new AttPacketCustomizer(customInfo);
391 log.info("Created AttPacketCustomizer");
392 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530393 default:
394 pktCustomizer = new PacketCustomizer(customInfo);
395 log.info("Created default PacketCustomizer");
396 break;
397 }
398 }
399
kartikey dubeye1545422019-05-22 12:53:45 +0000400 private void getConfiguredAaaServerAddress() {
401 try {
402 InetAddress address;
403 if (newCfg.radiusHostName() != null) {
404 address = InetAddress.getByName(newCfg.radiusHostName());
405 } else {
406 address = newCfg.radiusIp();
407 }
408
409 configuredAaaServerAddress = address.getHostAddress();
410 } catch (UnknownHostException uhe) {
411 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
412 }
413 }
414
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000415 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
416 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000417 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
418 }
419 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000420
421 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
422 byte[] newHash = new byte[16];
423 Arrays.fill(newHash, (byte) 0);
424 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
425 byte[] authenticator = radiusPacket.getAuthenticator();
426 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
427 radiusPacket.setAuthenticator(requestAuthenticator);
428 // Calculate the MD5 HMAC based on the message
429 try {
430 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
431 Mac mac = Mac.getInstance("HmacMD5");
432 mac.init(keySpec);
433 newHash = mac.doFinal(radiusPacket.serialize());
434 } catch (Exception e) {
435 log.error("Failed to generate message authenticator: {}", e.getMessage());
436 }
437 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
438 radiusPacket.setAuthenticator(authenticator);
439 // Compare the calculated Message-Authenticator with the one in the message
440 return Arrays.equals(newHash, messageAuthenticator);
441 }
kartikey dubeye1545422019-05-22 12:53:45 +0000442 public void checkForPacketFromUnknownServer(String hostAddress) {
443 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000444 getConfiguredAaaServerAddress();
445 if (!hostAddress.equals(configuredAaaServerAddress)) {
446 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
447 }
kartikey dubeye1545422019-05-22 12:53:45 +0000448 }
449 }
450
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100451 /**
452 * Send RADIUS packet to the RADIUS server.
453 *
454 * @param radiusPacket RADIUS packet to be sent to server.
455 * @param inPkt Incoming EAPOL packet
456 */
457 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000458 outPacketSet.add(radiusPacket.getIdentifier());
459 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
460 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000461 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100462 impl.sendRadiusPacket(radiusPacket, inPkt);
463 }
Ray Milkey967776a2015-10-07 14:37:17 -0700464
Jonathan Hart612651f2019-11-25 09:21:43 -0800465 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100466 * Handles RADIUS packets.
467 *
468 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Jonathan Hart4731dd92018-05-02 17:30:05 -0700469 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100470 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800471 public void handleRadiusPacket(RADIUS radiusPacket) throws DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700472 if (log.isTraceEnabled()) {
473 log.trace("Received RADIUS packet {}", radiusPacket);
474 }
Shubham Sharma4900ce62019-06-19 14:18:50 +0000475 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
476 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
477 return;
478 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800479
480 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
481 String sessionId = idManager.getSessionId(identifier);
482
483 if (sessionId == null) {
484 log.error("Invalid packet identifier {}, could not find corresponding "
485 + "state machine ... exiting", radiusPacket.getIdentifier());
486 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
487 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
488 return;
489 }
490
491 idManager.releaseIdentifier(identifier);
492 StateMachine stateMachine = stateMachines.get(sessionId);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100493 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700494 log.error("Invalid packet identifier {}, could not find corresponding "
495 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000496 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
497 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100498 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700499 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000500
501 //instance of StateMachine using the sessionId for updating machine stats
Jonathan Hart612651f2019-11-25 09:21:43 -0800502 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000503
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100504 EAP eapPayload;
505 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000506 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000507
508 //increasing packets and octets received from server
509 machineStats.incrementTotalPacketsReceived();
510 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
511
kartikey dubeye1545422019-05-22 12:53:45 +0000512 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
513 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
514 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
515 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100516 switch (radiusPacket.getCode()) {
517 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400518 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100519 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
520 byte[] challengeState = null;
521 if (radiusAttrState != null) {
522 challengeState = radiusAttrState.getValue();
523 }
524 eapPayload = radiusPacket.decapsulateMessage();
525 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
526 eth = buildEapolResponse(stateMachine.supplicantAddress(),
527 MacAddress.valueOf(nasMacAddress),
528 stateMachine.vlanId(),
529 EAPOL.EAPOL_PACKET,
530 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400531 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000532 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000533 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000534 outPacketSupp.add(eapPayload.getIdentifier());
535 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000536 //increasing packets send to server
537 machineStats.incrementTotalPacketsSent();
538 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100539 break;
540 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400541 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100542 //send an EAPOL - Success to the supplicant.
543 byte[] eapMessageSuccess =
544 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700545 eapPayload = EAP.deserializer().deserialize(
546 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100547 eth = buildEapolResponse(stateMachine.supplicantAddress(),
548 MacAddress.valueOf(nasMacAddress),
549 stateMachine.vlanId(),
550 EAPOL.EAPOL_PACKET,
551 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400552 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000553 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
554 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100555
556 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000557 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000558 //increasing packets send to server
559 machineStats.incrementTotalPacketsSent();
560 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100561 break;
562 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400563 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100564 //send an EAPOL - Failure to the supplicant.
565 byte[] eapMessageFailure;
566 eapPayload = new EAP();
567 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
568 if (radiusAttrEap == null) {
569 eapPayload.setCode(EAP.FAILURE);
570 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
571 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
572 } else {
573 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700574 eapPayload = EAP.deserializer().deserialize(
575 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100576 }
577 eth = buildEapolResponse(stateMachine.supplicantAddress(),
578 MacAddress.valueOf(nasMacAddress),
579 stateMachine.vlanId(),
580 EAPOL.EAPOL_PACKET,
581 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400582 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000583 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
584 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
585
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100586 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000587 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000588 //increasing packets send to server
589 machineStats.incrementTotalPacketsSent();
590 machineStats.incrementTotalOctetSent(eapPayload.getLength());
591 //pushing machine stats to kafka
592 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
593 aaaSupplicantStatsManager.getMachineStatsDelegate()
594 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, machineObj));
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100595 break;
596 default:
597 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000598 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000599 //increasing packets received to server
600 machineStats.incrementTotalPacketsReceived();
601 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100602 }
kartikey dubeye1545422019-05-22 12:53:45 +0000603 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700604 }
605
Ray Milkey967776a2015-10-07 14:37:17 -0700606 /**
607 * Send the ethernet packet to the supplicant.
608 *
609 * @param ethernetPkt the ethernet packet
610 * @param connectPoint the connect point to send out
611 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000612 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700613 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
614 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
615 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000616 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700617 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700618 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
619 eap, ethernetPkt, connectPoint);
620 }
Ray Milkey967776a2015-10-07 14:37:17 -0700621 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000622 if (isChallengeResponse) {
623 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
624 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000625 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
626 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700627 }
628
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400629 @Override
630 public String toString() {
631 return ToStringBuilder.reflectionToString(this);
632 }
633
Jonathan Hart612651f2019-11-25 09:21:43 -0800634 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800635 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
636 return authentications.asJavaMap().values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800637 }
638
639 @Override
640 public boolean removeAuthenticationStateByMac(MacAddress mac) {
641
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800642 Optional<Versioned<AuthenticationRecord>> r = authentications.values().stream()
643 .filter(v -> v.value().supplicantAddress().equals(mac))
644 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800645
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800646 if (r.isEmpty()) {
647 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800648 }
649
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800650 Versioned<AuthenticationRecord> removed =
651 authentications.remove(r.get().value().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800652
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800653 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800654 }
655
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800656 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800657 return stateMachines.get(sessionId);
658 }
659
660 private String sessionId(ConnectPoint cp) {
661 return cp.deviceId().toString() + cp.port().toString();
662 }
663
Ari Saha89831742015-06-26 10:31:48 -0700664 // our handler defined as a private inner class
665
666 /**
667 * Packet processor responsible for forwarding packets along their paths.
668 */
669 private class ReactivePacketProcessor implements PacketProcessor {
670 @Override
671 public void process(PacketContext context) {
672
673 // Extract the original Ethernet frame from the packet information
674 InboundPacket pkt = context.inPacket();
675 Ethernet ethPkt = pkt.parsed();
676 if (ethPkt == null) {
677 return;
678 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100679
Jonathan Hart612651f2019-11-25 09:21:43 -0800680 // identify if incoming packet comes from supplicant (EAP) or RADIUS
681 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
682 case EAPOL:
683 handleSupplicantPacket(context.inPacket());
684 break;
685 default:
686 // any other packets let the specific implementation handle
687 impl.handlePacketFromServer(context);
Ari Saha89831742015-06-26 10:31:48 -0700688 }
689 }
690
Ray Milkey9eb293f2015-09-30 15:09:17 -0700691 /**
692 * Creates and initializes common fields of a RADIUS packet.
693 *
Ray Milkey967776a2015-10-07 14:37:17 -0700694 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700695 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700696 * @return RADIUS packet
697 */
Ray Milkey967776a2015-10-07 14:37:17 -0700698 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700699 RADIUS radiusPayload =
700 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
701 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700702
703 // set Request Authenticator in StateMachine
704 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
705
Ray Milkey9eb293f2015-09-30 15:09:17 -0700706 radiusPayload.setIdentifier(identifier);
707 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700708 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700709
710 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800711 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700712
713 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700714
715 return radiusPayload;
716 }
Ari Saha89831742015-06-26 10:31:48 -0700717
718 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700719 * Handles PAE packets (supplicant).
720 *
721 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700722 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800723 private void handleSupplicantPacket(InboundPacket inPacket) {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700724 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700725 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800726 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700727
Jonathan Harta46dddf2015-06-30 15:31:20 -0700728 DeviceId deviceId = inPacket.receivedFrom().deviceId();
729 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800730 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700731 EAPOL eapol = (EAPOL) ethPkt.getPayload();
732 if (log.isTraceEnabled()) {
733 log.trace("Received EAPOL packet {} in enclosing packet {} from "
734 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
735 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100736 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700737
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000738 short pktlen = eapol.getPacketLength();
739 byte[] eapPayLoadBuffer = eapol.serialize();
740 int len = eapPayLoadBuffer.length;
741 if (len != (HEADER_LENGTH + pktlen)) {
742 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
743 return;
744 }
745 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
746 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
747 return;
748 }
749 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
750 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
751 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800752
753 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id -> new StateMachine(id, executor));
754 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700755
Ari Saha89831742015-06-26 10:31:48 -0700756 switch (eapol.getEapolType()) {
757 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400758 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700759 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800760 stateMachine.setSupplicantAddress(srcMac);
Jonathan Hart5db44532018-07-12 18:13:54 -0700761 stateMachine.start();
Jonathan Hart612651f2019-11-25 09:21:43 -0800762
Shubham Sharma1f193582019-07-11 12:12:41 +0000763 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700764 //send an EAP Request/Identify to the supplicant
765 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100766 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
767 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
768 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800769 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700770 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100771 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400772
Ray Milkeyf51eba22015-09-25 10:24:23 -0700773 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400774 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000775 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000776 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
Ari Saha89831742015-06-26 10:31:48 -0700777
778 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800779 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400780 log.debug("EAP packet: EAPOL_LOGOFF");
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000781 //posting the machine stat data for current supplicant device.
782 if (stateMachine.getSessionTerminateReason() == null ||
783 stateMachine.getSessionTerminateReason().equals("")) {
784 stateMachine.setSessionTerminateReason(
785 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
786 }
787 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
788 aaaSupplicantStatsManager.getMachineStatsDelegate()
789 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Ray Milkeyb34b4962016-01-04 10:24:43 -0800790 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
791 stateMachine.logoff();
Shubham Sharma1f193582019-07-11 12:12:41 +0000792 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800793 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000794 if (stateMachine.state() == StateMachine.STATE_IDLE) {
795 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
796 }
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800797
798 break;
Ari Saha89831742015-06-26 10:31:48 -0700799 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700800 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700801 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700802 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000803 Byte identifier = new Byte(eapPacket.getIdentifier());
Ari Saha89831742015-06-26 10:31:48 -0700804
Jonathan Hart612651f2019-11-25 09:21:43 -0800805 // get identifier for request and store mapping to session ID
806 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
807
Ari Saha89831742015-06-26 10:31:48 -0700808 byte dataType = eapPacket.getDataType();
809 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700810
Ray Milkey9eb293f2015-09-30 15:09:17 -0700811 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400812 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharma1e43c562019-06-19 14:18:12 +0000813 //Setting the time of this response from RG, only when its not a re-transmission.
814 if (stateMachine.getLastPacketReceivedTime() == 0) {
815 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
816 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700817 // request id access to RADIUS
818 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700819
Jonathan Hart612651f2019-11-25 09:21:43 -0800820 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100821 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800822 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700823
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100824 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000825 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000826 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700827 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000828 if (stateMachine.state() == StateMachine.STATE_PENDING) {
829 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000830 stateMachine.incrementTotalPacketsSent();
831 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
kartikey dubeye1545422019-05-22 12:53:45 +0000832 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700833 stateMachine.requestAccess();
834 break;
Ari Saha89831742015-06-26 10:31:48 -0700835 case EAP.ATTR_MD5:
Shubham Sharma1e43c562019-06-19 14:18:12 +0000836 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400837 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700838 // verify if the EAP identifier corresponds to the
839 // challenge identifier from the client state
840 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700841 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700842 //send the RADIUS challenge response
Jonathan Hart612651f2019-11-25 09:21:43 -0800843 radiusPayload = getRadiusPayload(stateMachine,
844 radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100845 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700846
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800847 if (stateMachine.challengeState() != null) {
848 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
849 stateMachine.challengeState());
850 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800851 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000852 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
853 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
854 outPacketSupp.remove(identifier);
855 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100856 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000857 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000858 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700859 }
860 break;
861 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400862 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700863 // request id access to RADIUS
Jonathan Hart612651f2019-11-25 09:21:43 -0800864 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100865 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700866
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800867 if (stateMachine.challengeState() != null) {
868 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
869 stateMachine.challengeState());
870 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700871 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700872
Jonathan Hart092dfb22015-11-16 23:05:21 -0800873 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000874 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
875 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
876 outPacketSupp.remove(identifier);
877 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100878 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000879 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000880 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700881
Ray Milkeyf3790b82015-10-21 16:28:08 -0700882 if (stateMachine.state() != StateMachine.STATE_PENDING) {
883 stateMachine.requestAccess();
884 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700885
Ari Saha89831742015-06-26 10:31:48 -0700886 break;
887 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400888 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700889 return;
890 }
891 break;
892 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400893 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700894 }
Shubham Sharma1f193582019-07-11 12:12:41 +0000895 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
896 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700897 }
Ray Milkey967776a2015-10-07 14:37:17 -0700898 }
899
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100900 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700901 * Delegate allowing the StateMachine to notify us of events.
902 */
903 private class InternalStateMachineDelegate implements StateMachineDelegate {
904
905 @Override
906 public void notify(AuthenticationEvent authenticationEvent) {
907 log.info("Auth event {} for {}",
908 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -0800909
910 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
911 handleStateMachineTimeout(authenticationEvent.subject());
912 }
913
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800914 AuthenticationRecord record = authenticationEvent.authenticationRecord();
915 if (record == null) {
916 authentications.remove(authenticationEvent.subject());
917 } else {
918 authentications.put(authenticationEvent.subject(), record);
919 }
920
Jonathan Hart5db44532018-07-12 18:13:54 -0700921 post(authenticationEvent);
922 }
923 }
924
Jonathan Hart612651f2019-11-25 09:21:43 -0800925 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
926 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
927
Andrea Campanellae66466a2020-02-03 14:05:45 +0000928 //pushing captured machine stats to kafka
929 stateMachine.setSessionTerminateReason("Time out");
930 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
931 .getSupplicantStats(stateMachine);
932 aaaSupplicantStatsManager.getMachineStatsDelegate()
933 .notify(new AaaMachineStatisticsEvent(
934 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
935
Jonathan Hart612651f2019-11-25 09:21:43 -0800936 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
937 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
938 }
939
940 StateMachine.deleteStateMachineMapping(stateMachine);
941 }
942
Jonathan Hart5db44532018-07-12 18:13:54 -0700943 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100944 * Configuration Listener, handles change in configuration.
945 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700946 private class InternalConfigListener implements NetworkConfigListener {
947
948 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800949 * Reconfigures the AAA application according to the
950 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700951 *
952 * @param cfg configuration object
953 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800954 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400955 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100956
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700957 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800958 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700959 } else {
960 newCfg = cfg;
961 }
962 if (newCfg.nasIp() != null) {
963 nasIpAddress = newCfg.nasIp();
964 }
965 if (newCfg.radiusIp() != null) {
966 radiusIpAddress = newCfg.radiusIp();
967 }
968 if (newCfg.radiusMac() != null) {
969 radiusMacAddress = newCfg.radiusMac();
970 }
971 if (newCfg.nasMac() != null) {
972 nasMacAddress = newCfg.nasMac();
973 }
974 if (newCfg.radiusSecret() != null) {
975 radiusSecret = newCfg.radiusSecret();
976 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100977
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530978 boolean reconfigureCustomizer = false;
979 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
980 customizer = newCfg.radiusPktCustomizer();
981 configurePacketCustomizer();
982 reconfigureCustomizer = true;
983 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100984
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530985 if (radiusConnectionType == null
986 || reconfigureCustomizer
987 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
988 radiusConnectionType = newCfg.radiusConnectionType();
989 if (impl != null) {
990 impl.withdrawIntercepts();
991 impl.clearLocalState();
992 }
993 configureRadiusCommunication();
994 impl.initializeLocalState(newCfg);
995 impl.requestIntercepts();
996 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100997 impl.clearLocalState();
998 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -0700999 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001000 }
1001
1002 @Override
1003 public void event(NetworkConfigEvent event) {
1004
1005 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1006 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001007 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001008
Jonathan Hart092dfb22015-11-16 23:05:21 -08001009 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001010 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001011
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001012 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001013 }
1014 }
1015 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001016
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001017 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1018 @Override
1019 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1020 if (event.type() == MapEvent.Type.REMOVE) {
1021 // remove local state machine if user has requested remove
1022 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1023 if (sm != null) {
1024 sm.stop();
1025 }
1026 }
1027 }
1028 }
1029
Amit Ghoshf739be52017-09-21 15:49:37 +01001030 private class InternalDeviceListener implements DeviceListener {
1031 @Override
1032 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001033 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001034 switch (event.type()) {
1035 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001036 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001037 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001038 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
1039 flushStateMachineSession(sessionId,
1040 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001041
Girish Kumar064084c2020-02-04 08:32:46 +00001042 break;
Andrea Campanellabba33672020-02-11 14:03:01 +01001043 case DEVICE_AVAILABILITY_CHANGED:
1044 if (!deviceService.isAvailable(deviceId)) {
1045 log.debug("Received DEVICE_AVAILABILITY_CHANGED event for {}, " +
1046 "went available to un-available", deviceId);
1047 clearAllSessionStateForDevice(deviceId);
1048 }
1049 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001050 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001051 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001052 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001053 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001054
Amit Ghoshf739be52017-09-21 15:49:37 +01001055 default:
1056 return;
1057 }
1058 }
Girish Kumar064084c2020-02-04 08:32:46 +00001059
Andrea Campanellabba33672020-02-11 14:03:01 +01001060 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1061 Set<String> associatedSessions = Sets.newHashSet();
1062 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1063 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1064 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1065 associatedSessions.add(stateMachineEntry.getKey());
1066 }
1067 }
1068
1069 for (String session : associatedSessions) {
1070 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1071 flushStateMachineSession(session,
1072 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
1073 }
1074 }
1075
Girish Kumar064084c2020-02-04 08:32:46 +00001076 private void flushStateMachineSession(String sessionId, String terminationReason) {
1077 StateMachine stateMachine = stateMachines.get(sessionId);
Girish Kumare5a1aa92020-02-14 14:08:54 +00001078 if (stateMachine == null) {
1079 // No active AAA sessions for this UNI port
1080 log.debug("No Active AAA Session found with Id {}", sessionId);
1081 return;
Girish Kumar064084c2020-02-04 08:32:46 +00001082 }
1083
Girish Kumare5a1aa92020-02-14 14:08:54 +00001084 stateMachine.setSessionTerminateReason(terminationReason);
1085
Girish Kumar064084c2020-02-04 08:32:46 +00001086 //pushing captured machine stats to kafka
1087 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1088 aaaSupplicantStatsManager.getMachineStatsDelegate()
1089 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
1090
1091 StateMachine removed = stateMachines.remove(sessionId);
1092 if (removed != null) {
1093 StateMachine.deleteStateMachineMapping(removed);
1094 }
1095 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001096 }
Girish Kumar064084c2020-02-04 08:32:46 +00001097
Shubham Sharma4900ce62019-06-19 14:18:50 +00001098 private class ServerStatusChecker implements Runnable {
1099 @Override
1100 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001101 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001102 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001103 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001104 radiusOperationalStatusService.getRadiusOprStDelegate()
1105 .notify(new RadiusOperationalStatusEvent(
1106 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1107 radiusOperationalStatusService.
1108 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001109 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001110
1111 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001112}