blob: e139b706c242e93ddd486cf169d2cc9774353222 [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;
Hardik Windlassd0b49692020-02-26 18:17:14 +000031import java.util.Map;
Girish Kumar064084c2020-02-04 08:32:46 +000032import java.util.Set;
33import java.util.Map.Entry;
34
Jonathan Hart932bedc2018-07-12 13:46:09 -070035import org.apache.commons.lang3.builder.ToStringBuilder;
Jonathan Hart4731dd92018-05-02 17:30:05 -070036import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070037import org.onlab.packet.EAP;
38import org.onlab.packet.EAPOL;
39import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070040import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070041import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070042import org.onlab.packet.RADIUS;
43import org.onlab.packet.RADIUSAttribute;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080044import org.onlab.util.KryoNamespace;
kartikey dubeye1545422019-05-22 12:53:45 +000045import org.onlab.util.Tools;
46import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070047import org.onosproject.core.ApplicationId;
48import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070049import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010050import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070051import org.onosproject.net.ConnectPoint;
52import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070053import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070054import org.onosproject.net.config.ConfigFactory;
55import org.onosproject.net.config.NetworkConfigEvent;
56import org.onosproject.net.config.NetworkConfigListener;
57import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010058import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010060import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070061import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070062import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070063import org.onosproject.net.packet.DefaultOutboundPacket;
64import org.onosproject.net.packet.InboundPacket;
65import org.onosproject.net.packet.OutboundPacket;
66import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070067import org.onosproject.net.packet.PacketProcessor;
68import org.onosproject.net.packet.PacketService;
Jonathan Hartc41227c2020-01-28 16:56:49 -080069import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080070import org.onosproject.store.service.ConsistentMap;
71import org.onosproject.store.service.MapEvent;
72import org.onosproject.store.service.MapEventListener;
73import org.onosproject.store.service.Serializer;
74import org.onosproject.store.service.StorageService;
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
Hardik Windlassd0b49692020-02-26 18:17:14 +0000178 private ConsistentMap<ConnectPoint, AuthenticationRecord> authenticationsConsistentMap;
179 private Map<ConnectPoint, AuthenticationRecord> authentications;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800180
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700181 // NAS IP address
182 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100183
184 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700185 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100186
187 // Parsed RADIUS server addresses
188 protected InetAddress radiusIpAddress;
189
190 // MAC address of RADIUS server or net hop router
191 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700192
193 // RADIUS server secret
194 protected String radiusSecret;
195
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100196 // bindings
197 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700198
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700199 // our application-specific event handler
200 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700201
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700202 // our unique identifier
203 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700204
Shubham Sharma1e43c562019-06-19 14:18:12 +0000205 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
206 protected int cleanupTimerTimeOutInMins;
207
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100208 // Setup specific customization/attributes on the RADIUS packets
209 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700210
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100211 // packet customizer to use
212 private String customizer;
213
214 // Type of connection to use to communicate with Radius server, options are
215 // "socket" or "packet_out"
216 private String radiusConnectionType;
217
Jonathan Hart5db44532018-07-12 18:13:54 -0700218 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100219 // server, socket based or packet_out based
220 RadiusCommunicator impl = null;
221
222 // latest configuration
223 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700224
Shubham Sharma4900ce62019-06-19 14:18:50 +0000225 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000226 ScheduledExecutorService executor;
227 String configuredAaaServerAddress;
Jonathan Hartc41227c2020-01-28 16:56:49 -0800228 HashSet<Byte> outPacketSet = new HashSet<>();
229 HashSet<Byte> outPacketSupp = new HashSet<>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000230 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
231 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700232 // Configuration properties factory
233 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800234 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
235 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700236 "AAA") {
237 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800238 public AaaConfig createConfig() {
239 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700240 }
241 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700242
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700243 // Listener for config changes
244 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700245
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800246 private final InternalMapEventListener mapListener = new InternalMapEventListener();
247
Jonathan Hart5db44532018-07-12 18:13:54 -0700248 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
249
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700250 /**
251 * Builds an EAPOL packet based on the given parameters.
252 *
253 * @param dstMac destination MAC address
254 * @param srcMac source MAC address
255 * @param vlan vlan identifier
256 * @param eapolType EAPOL type
257 * @param eap EAP payload
258 * @return Ethernet frame
259 */
260 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100261 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700262
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700263 Ethernet eth = new Ethernet();
264 eth.setDestinationMACAddress(dstMac.toBytes());
265 eth.setSourceMACAddress(srcMac.toBytes());
266 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
267 if (vlan != Ethernet.VLAN_UNTAGGED) {
268 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100269 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700270 }
271 //eapol header
272 EAPOL eapol = new EAPOL();
273 eapol.setEapolType(eapolType);
274 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700275
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700276 //eap part
277 eapol.setPayload(eap);
278
279 eth.setPayload(eapol);
280 eth.setPad(true);
281 return eth;
282 }
Ari Saha89831742015-06-26 10:31:48 -0700283
Ari Saha89831742015-06-26 10:31:48 -0700284 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000285 public void activate(ComponentContext context) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800286 idManager = new IdentifierManager();
287 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800288 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800289
290 KryoNamespace authSerializer = KryoNamespace.newBuilder()
Jonathan Hartc41227c2020-01-28 16:56:49 -0800291 .register(KryoNamespaces.API)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800292 .register(AuthenticationRecord.class)
293 .build();
294
Hardik Windlassd0b49692020-02-26 18:17:14 +0000295 authenticationsConsistentMap = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800296 .withApplicationId(appId)
297 .withName("authentications")
298 .withSerializer(Serializer.using(authSerializer))
299 .build();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000300 authenticationsConsistentMap.addListener(mapListener);
301 authentications = authenticationsConsistentMap.asJavaMap();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800302
Jonathan Hart5db44532018-07-12 18:13:54 -0700303 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400304 netCfgService.addListener(cfgListener);
305 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000306 cfgService.registerProperties(getClass());
307 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000308 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530309 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800310 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400311 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530312 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700313 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700314 packetService.addProcessor(processor, PacketProcessor.director(2));
Jonathan Hart5db44532018-07-12 18:13:54 -0700315 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000316 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
317 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100318 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100319 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100320 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000321 getConfiguredAaaServerAddress();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000322 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000323 executor = Executors.newScheduledThreadPool(3);
324
Shubham Sharma4900ce62019-06-19 14:18:50 +0000325 scheduledStatusServerChecker = executor.scheduleAtFixedRate(new ServerStatusChecker(), 0,
326 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100327
Jian Li13c67162015-12-09 13:20:34 -0800328 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700329 }
330
331 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000332 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100333 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700334 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530335 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000336 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700337 StateMachine.unsetDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100338 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100339 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700340 eventDispatcher.removeSink(AuthenticationEvent.class);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000341 scheduledStatusServerChecker.cancel(true);
kartikey dubeye1545422019-05-22 12:53:45 +0000342 executor.shutdown();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800343
Hardik Windlassd0b49692020-02-26 18:17:14 +0000344 authenticationsConsistentMap.removeListener(mapListener);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800345
Jian Li13c67162015-12-09 13:20:34 -0800346 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700347 }
kartikey dubeye1545422019-05-22 12:53:45 +0000348 @Modified
349 public void modified(ComponentContext context) {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000350 Dictionary<String, Object> properties = context.getProperties();
351
Jonathan Hartc41227c2020-01-28 16:56:49 -0800352 String s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
Shubham Sharma4900ce62019-06-19 14:18:50 +0000353 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
354 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
355 : Integer.parseInt(s.trim());
356
357 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
358 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
359 : Integer.parseInt(s.trim());
360
361 s = Tools.get(properties, "operationalStatusEvaluationMode");
362 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
363
364 radiusOperationalStatusService
365 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
366 RadiusOperationalStatusEvaluationMode newEvaluationMode =
367 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
368 if (newEvaluationMode != null) {
369 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
370 operationalStatusEvaluationMode = newEvaluationModeString;
371 } else {
372 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
373 }
kartikey dubeye1545422019-05-22 12:53:45 +0000374 }
375
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000376 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530377 if (radiusConnectionType.toLowerCase().equals("socket")) {
378 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
379 } else {
380 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
381 deviceService, subsService, pktCustomizer, this);
382 }
383 }
384
385 private void configurePacketCustomizer() {
386 switch (customizer.toLowerCase()) {
387 case "sample":
388 pktCustomizer = new SamplePacketCustomizer(customInfo);
389 log.info("Created SamplePacketCustomizer");
390 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800391 case "att":
392 pktCustomizer = new AttPacketCustomizer(customInfo);
393 log.info("Created AttPacketCustomizer");
394 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530395 default:
396 pktCustomizer = new PacketCustomizer(customInfo);
397 log.info("Created default PacketCustomizer");
398 break;
399 }
400 }
401
kartikey dubeye1545422019-05-22 12:53:45 +0000402 private void getConfiguredAaaServerAddress() {
403 try {
404 InetAddress address;
405 if (newCfg.radiusHostName() != null) {
406 address = InetAddress.getByName(newCfg.radiusHostName());
407 } else {
408 address = newCfg.radiusIp();
409 }
410
411 configuredAaaServerAddress = address.getHostAddress();
412 } catch (UnknownHostException uhe) {
413 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
414 }
415 }
416
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000417 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
418 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000419 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
420 }
421 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000422
423 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
424 byte[] newHash = new byte[16];
425 Arrays.fill(newHash, (byte) 0);
426 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
427 byte[] authenticator = radiusPacket.getAuthenticator();
428 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
429 radiusPacket.setAuthenticator(requestAuthenticator);
430 // Calculate the MD5 HMAC based on the message
431 try {
432 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
433 Mac mac = Mac.getInstance("HmacMD5");
434 mac.init(keySpec);
435 newHash = mac.doFinal(radiusPacket.serialize());
436 } catch (Exception e) {
437 log.error("Failed to generate message authenticator: {}", e.getMessage());
438 }
439 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
440 radiusPacket.setAuthenticator(authenticator);
441 // Compare the calculated Message-Authenticator with the one in the message
442 return Arrays.equals(newHash, messageAuthenticator);
443 }
kartikey dubeye1545422019-05-22 12:53:45 +0000444 public void checkForPacketFromUnknownServer(String hostAddress) {
445 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000446 getConfiguredAaaServerAddress();
447 if (!hostAddress.equals(configuredAaaServerAddress)) {
448 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
449 }
kartikey dubeye1545422019-05-22 12:53:45 +0000450 }
451 }
452
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100453 /**
454 * Send RADIUS packet to the RADIUS server.
455 *
456 * @param radiusPacket RADIUS packet to be sent to server.
457 * @param inPkt Incoming EAPOL packet
458 */
459 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000460 outPacketSet.add(radiusPacket.getIdentifier());
461 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
462 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000463 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100464 impl.sendRadiusPacket(radiusPacket, inPkt);
465 }
Ray Milkey967776a2015-10-07 14:37:17 -0700466
Jonathan Hart612651f2019-11-25 09:21:43 -0800467 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100468 * Handles RADIUS packets.
469 *
470 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Jonathan Hart4731dd92018-05-02 17:30:05 -0700471 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100472 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800473 public void handleRadiusPacket(RADIUS radiusPacket) throws DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700474 if (log.isTraceEnabled()) {
475 log.trace("Received RADIUS packet {}", radiusPacket);
476 }
Shubham Sharma4900ce62019-06-19 14:18:50 +0000477 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
478 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
479 return;
480 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800481
482 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
483 String sessionId = idManager.getSessionId(identifier);
484
485 if (sessionId == null) {
486 log.error("Invalid packet identifier {}, could not find corresponding "
487 + "state machine ... exiting", radiusPacket.getIdentifier());
488 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
489 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
490 return;
491 }
492
493 idManager.releaseIdentifier(identifier);
494 StateMachine stateMachine = stateMachines.get(sessionId);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100495 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700496 log.error("Invalid packet identifier {}, could not find corresponding "
497 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000498 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
499 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100500 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700501 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000502
503 //instance of StateMachine using the sessionId for updating machine stats
Jonathan Hart612651f2019-11-25 09:21:43 -0800504 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000505
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100506 EAP eapPayload;
507 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000508 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000509
510 //increasing packets and octets received from server
511 machineStats.incrementTotalPacketsReceived();
512 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
513
kartikey dubeye1545422019-05-22 12:53:45 +0000514 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
515 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
516 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
517 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100518 switch (radiusPacket.getCode()) {
519 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400520 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100521 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
522 byte[] challengeState = null;
523 if (radiusAttrState != null) {
524 challengeState = radiusAttrState.getValue();
525 }
526 eapPayload = radiusPacket.decapsulateMessage();
527 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
528 eth = buildEapolResponse(stateMachine.supplicantAddress(),
529 MacAddress.valueOf(nasMacAddress),
530 stateMachine.vlanId(),
531 EAPOL.EAPOL_PACKET,
532 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400533 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000534 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000535 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000536 outPacketSupp.add(eapPayload.getIdentifier());
537 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000538 //increasing packets send to server
539 machineStats.incrementTotalPacketsSent();
540 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100541 break;
542 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400543 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100544 //send an EAPOL - Success to the supplicant.
545 byte[] eapMessageSuccess =
546 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700547 eapPayload = EAP.deserializer().deserialize(
548 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100549 eth = buildEapolResponse(stateMachine.supplicantAddress(),
550 MacAddress.valueOf(nasMacAddress),
551 stateMachine.vlanId(),
552 EAPOL.EAPOL_PACKET,
553 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400554 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000555 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
556 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100557
558 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000559 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000560 //increasing packets send to server
561 machineStats.incrementTotalPacketsSent();
562 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100563 break;
564 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400565 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100566 //send an EAPOL - Failure to the supplicant.
567 byte[] eapMessageFailure;
568 eapPayload = new EAP();
569 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
570 if (radiusAttrEap == null) {
571 eapPayload.setCode(EAP.FAILURE);
572 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
573 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
574 } else {
575 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700576 eapPayload = EAP.deserializer().deserialize(
577 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100578 }
579 eth = buildEapolResponse(stateMachine.supplicantAddress(),
580 MacAddress.valueOf(nasMacAddress),
581 stateMachine.vlanId(),
582 EAPOL.EAPOL_PACKET,
583 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400584 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000585 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
586 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
587
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100588 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000589 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000590 //increasing packets send to server
591 machineStats.incrementTotalPacketsSent();
592 machineStats.incrementTotalOctetSent(eapPayload.getLength());
593 //pushing machine stats to kafka
594 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
595 aaaSupplicantStatsManager.getMachineStatsDelegate()
596 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, machineObj));
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100597 break;
598 default:
599 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000600 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000601 //increasing packets received to server
602 machineStats.incrementTotalPacketsReceived();
603 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100604 }
kartikey dubeye1545422019-05-22 12:53:45 +0000605 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700606 }
607
Ray Milkey967776a2015-10-07 14:37:17 -0700608 /**
609 * Send the ethernet packet to the supplicant.
610 *
611 * @param ethernetPkt the ethernet packet
612 * @param connectPoint the connect point to send out
613 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000614 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700615 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
616 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
617 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000618 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700619 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700620 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
621 eap, ethernetPkt, connectPoint);
622 }
Ray Milkey967776a2015-10-07 14:37:17 -0700623 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000624 if (isChallengeResponse) {
625 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
626 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000627 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
628 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700629 }
630
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400631 @Override
632 public String toString() {
633 return ToStringBuilder.reflectionToString(this);
634 }
635
Jonathan Hart612651f2019-11-25 09:21:43 -0800636 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800637 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
Hardik Windlassd0b49692020-02-26 18:17:14 +0000638 return authentications.values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800639 }
640
641 @Override
642 public boolean removeAuthenticationStateByMac(MacAddress mac) {
643
Hardik Windlassd0b49692020-02-26 18:17:14 +0000644 Optional<AuthenticationRecord> r = authentications.values().stream()
645 .filter(v -> v.supplicantAddress().equals(mac))
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800646 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800647
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800648 if (r.isEmpty()) {
649 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800650 }
651
Hardik Windlassd0b49692020-02-26 18:17:14 +0000652 AuthenticationRecord removed =
653 authentications.remove(r.get().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800654
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800655 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800656 }
657
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800658 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800659 return stateMachines.get(sessionId);
660 }
661
662 private String sessionId(ConnectPoint cp) {
663 return cp.deviceId().toString() + cp.port().toString();
664 }
665
Ari Saha89831742015-06-26 10:31:48 -0700666 // our handler defined as a private inner class
667
668 /**
669 * Packet processor responsible for forwarding packets along their paths.
670 */
671 private class ReactivePacketProcessor implements PacketProcessor {
672 @Override
673 public void process(PacketContext context) {
674
675 // Extract the original Ethernet frame from the packet information
676 InboundPacket pkt = context.inPacket();
677 Ethernet ethPkt = pkt.parsed();
678 if (ethPkt == null) {
679 return;
680 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100681
Jonathan Hart612651f2019-11-25 09:21:43 -0800682 // identify if incoming packet comes from supplicant (EAP) or RADIUS
683 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
684 case EAPOL:
685 handleSupplicantPacket(context.inPacket());
686 break;
687 default:
688 // any other packets let the specific implementation handle
689 impl.handlePacketFromServer(context);
Ari Saha89831742015-06-26 10:31:48 -0700690 }
691 }
692
Ray Milkey9eb293f2015-09-30 15:09:17 -0700693 /**
694 * Creates and initializes common fields of a RADIUS packet.
695 *
Ray Milkey967776a2015-10-07 14:37:17 -0700696 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700697 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700698 * @return RADIUS packet
699 */
Ray Milkey967776a2015-10-07 14:37:17 -0700700 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700701 RADIUS radiusPayload =
702 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
703 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700704
705 // set Request Authenticator in StateMachine
706 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
707
Ray Milkey9eb293f2015-09-30 15:09:17 -0700708 radiusPayload.setIdentifier(identifier);
709 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700710 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700711
712 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800713 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700714
715 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700716
717 return radiusPayload;
718 }
Ari Saha89831742015-06-26 10:31:48 -0700719
720 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700721 * Handles PAE packets (supplicant).
722 *
723 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700724 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800725 private void handleSupplicantPacket(InboundPacket inPacket) {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700726 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700727 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800728 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700729
Jonathan Harta46dddf2015-06-30 15:31:20 -0700730 DeviceId deviceId = inPacket.receivedFrom().deviceId();
731 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800732 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700733 EAPOL eapol = (EAPOL) ethPkt.getPayload();
734 if (log.isTraceEnabled()) {
735 log.trace("Received EAPOL packet {} in enclosing packet {} from "
736 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
737 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100738 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700739
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000740 short pktlen = eapol.getPacketLength();
741 byte[] eapPayLoadBuffer = eapol.serialize();
742 int len = eapPayLoadBuffer.length;
743 if (len != (HEADER_LENGTH + pktlen)) {
744 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
745 return;
746 }
747 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
748 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
749 return;
750 }
751 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
752 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
753 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800754
755 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id -> new StateMachine(id, executor));
756 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700757
Ari Saha89831742015-06-26 10:31:48 -0700758 switch (eapol.getEapolType()) {
759 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400760 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700761 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800762 stateMachine.setSupplicantAddress(srcMac);
Jonathan Hart5db44532018-07-12 18:13:54 -0700763 stateMachine.start();
Jonathan Hart612651f2019-11-25 09:21:43 -0800764
Shubham Sharma1f193582019-07-11 12:12:41 +0000765 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700766 //send an EAP Request/Identify to the supplicant
767 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100768 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
769 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
770 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800771 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700772 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100773 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400774
Ray Milkeyf51eba22015-09-25 10:24:23 -0700775 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400776 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000777 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000778 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
Ari Saha89831742015-06-26 10:31:48 -0700779
780 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800781 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400782 log.debug("EAP packet: EAPOL_LOGOFF");
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000783 //posting the machine stat data for current supplicant device.
784 if (stateMachine.getSessionTerminateReason() == null ||
785 stateMachine.getSessionTerminateReason().equals("")) {
786 stateMachine.setSessionTerminateReason(
787 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
788 }
789 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
790 aaaSupplicantStatsManager.getMachineStatsDelegate()
791 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Ray Milkeyb34b4962016-01-04 10:24:43 -0800792 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
793 stateMachine.logoff();
Shubham Sharma1f193582019-07-11 12:12:41 +0000794 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800795 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000796 if (stateMachine.state() == StateMachine.STATE_IDLE) {
797 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
798 }
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800799
800 break;
Ari Saha89831742015-06-26 10:31:48 -0700801 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700802 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700803 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700804 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000805 Byte identifier = new Byte(eapPacket.getIdentifier());
Ari Saha89831742015-06-26 10:31:48 -0700806
Jonathan Hart612651f2019-11-25 09:21:43 -0800807 // get identifier for request and store mapping to session ID
808 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
809
Ari Saha89831742015-06-26 10:31:48 -0700810 byte dataType = eapPacket.getDataType();
811 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700812
Ray Milkey9eb293f2015-09-30 15:09:17 -0700813 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400814 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharma1e43c562019-06-19 14:18:12 +0000815 //Setting the time of this response from RG, only when its not a re-transmission.
816 if (stateMachine.getLastPacketReceivedTime() == 0) {
817 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
818 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700819 // request id access to RADIUS
820 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700821
Jonathan Hart612651f2019-11-25 09:21:43 -0800822 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100823 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800824 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700825
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100826 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000827 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000828 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700829 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000830 if (stateMachine.state() == StateMachine.STATE_PENDING) {
831 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000832 stateMachine.incrementTotalPacketsSent();
833 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
kartikey dubeye1545422019-05-22 12:53:45 +0000834 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700835 stateMachine.requestAccess();
836 break;
Ari Saha89831742015-06-26 10:31:48 -0700837 case EAP.ATTR_MD5:
Shubham Sharma1e43c562019-06-19 14:18:12 +0000838 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400839 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700840 // verify if the EAP identifier corresponds to the
841 // challenge identifier from the client state
842 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700843 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700844 //send the RADIUS challenge response
Jonathan Hart612651f2019-11-25 09:21:43 -0800845 radiusPayload = getRadiusPayload(stateMachine,
846 radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100847 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700848
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800849 if (stateMachine.challengeState() != null) {
850 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
851 stateMachine.challengeState());
852 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800853 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000854 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
855 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
856 outPacketSupp.remove(identifier);
857 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100858 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000859 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000860 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700861 }
862 break;
863 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400864 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700865 // request id access to RADIUS
Jonathan Hart612651f2019-11-25 09:21:43 -0800866 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100867 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700868
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800869 if (stateMachine.challengeState() != null) {
870 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
871 stateMachine.challengeState());
872 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700873 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700874
Jonathan Hart092dfb22015-11-16 23:05:21 -0800875 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000876 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
877 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
878 outPacketSupp.remove(identifier);
879 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100880 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000881 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000882 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700883
Ray Milkeyf3790b82015-10-21 16:28:08 -0700884 if (stateMachine.state() != StateMachine.STATE_PENDING) {
885 stateMachine.requestAccess();
886 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700887
Ari Saha89831742015-06-26 10:31:48 -0700888 break;
889 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400890 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700891 return;
892 }
893 break;
894 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400895 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700896 }
Shubham Sharma1f193582019-07-11 12:12:41 +0000897 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
898 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700899 }
Ray Milkey967776a2015-10-07 14:37:17 -0700900 }
901
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100902 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700903 * Delegate allowing the StateMachine to notify us of events.
904 */
905 private class InternalStateMachineDelegate implements StateMachineDelegate {
906
907 @Override
908 public void notify(AuthenticationEvent authenticationEvent) {
909 log.info("Auth event {} for {}",
910 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -0800911
912 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
913 handleStateMachineTimeout(authenticationEvent.subject());
914 }
915
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800916 AuthenticationRecord record = authenticationEvent.authenticationRecord();
917 if (record == null) {
918 authentications.remove(authenticationEvent.subject());
919 } else {
920 authentications.put(authenticationEvent.subject(), record);
921 }
922
Jonathan Hart5db44532018-07-12 18:13:54 -0700923 post(authenticationEvent);
924 }
925 }
926
Jonathan Hart612651f2019-11-25 09:21:43 -0800927 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
928 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
929
Andrea Campanellae66466a2020-02-03 14:05:45 +0000930 //pushing captured machine stats to kafka
931 stateMachine.setSessionTerminateReason("Time out");
932 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
933 .getSupplicantStats(stateMachine);
934 aaaSupplicantStatsManager.getMachineStatsDelegate()
935 .notify(new AaaMachineStatisticsEvent(
936 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
937
Jonathan Hart612651f2019-11-25 09:21:43 -0800938 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
939 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
940 }
941
942 StateMachine.deleteStateMachineMapping(stateMachine);
943 }
944
Jonathan Hart5db44532018-07-12 18:13:54 -0700945 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100946 * Configuration Listener, handles change in configuration.
947 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700948 private class InternalConfigListener implements NetworkConfigListener {
949
950 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800951 * Reconfigures the AAA application according to the
952 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700953 *
954 * @param cfg configuration object
955 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800956 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400957 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100958
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700959 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800960 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700961 } else {
962 newCfg = cfg;
963 }
964 if (newCfg.nasIp() != null) {
965 nasIpAddress = newCfg.nasIp();
966 }
967 if (newCfg.radiusIp() != null) {
968 radiusIpAddress = newCfg.radiusIp();
969 }
970 if (newCfg.radiusMac() != null) {
971 radiusMacAddress = newCfg.radiusMac();
972 }
973 if (newCfg.nasMac() != null) {
974 nasMacAddress = newCfg.nasMac();
975 }
976 if (newCfg.radiusSecret() != null) {
977 radiusSecret = newCfg.radiusSecret();
978 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100979
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530980 boolean reconfigureCustomizer = false;
981 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
982 customizer = newCfg.radiusPktCustomizer();
983 configurePacketCustomizer();
984 reconfigureCustomizer = true;
985 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100986
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530987 if (radiusConnectionType == null
988 || reconfigureCustomizer
989 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
990 radiusConnectionType = newCfg.radiusConnectionType();
991 if (impl != null) {
992 impl.withdrawIntercepts();
993 impl.clearLocalState();
994 }
995 configureRadiusCommunication();
996 impl.initializeLocalState(newCfg);
997 impl.requestIntercepts();
998 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100999 impl.clearLocalState();
1000 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -07001001 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001002 }
1003
1004 @Override
1005 public void event(NetworkConfigEvent event) {
1006
1007 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1008 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001009 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001010
Jonathan Hart092dfb22015-11-16 23:05:21 -08001011 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001012 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001013
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001014 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001015 }
1016 }
1017 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001018
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001019 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1020 @Override
1021 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1022 if (event.type() == MapEvent.Type.REMOVE) {
1023 // remove local state machine if user has requested remove
1024 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1025 if (sm != null) {
1026 sm.stop();
1027 }
1028 }
1029 }
1030 }
1031
Amit Ghoshf739be52017-09-21 15:49:37 +01001032 private class InternalDeviceListener implements DeviceListener {
1033 @Override
1034 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001035 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001036 switch (event.type()) {
1037 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001038 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001039 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001040 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
Hardik Windlass75c67712020-02-21 10:57:20 +00001041
Girish Kumar064084c2020-02-04 08:32:46 +00001042 flushStateMachineSession(sessionId,
1043 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001044
Girish Kumar064084c2020-02-04 08:32:46 +00001045 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001046 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001047 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001048 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001049 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001050
Amit Ghoshf739be52017-09-21 15:49:37 +01001051 default:
1052 return;
1053 }
1054 }
Girish Kumar064084c2020-02-04 08:32:46 +00001055
Andrea Campanellabba33672020-02-11 14:03:01 +01001056 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1057 Set<String> associatedSessions = Sets.newHashSet();
1058 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1059 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1060 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1061 associatedSessions.add(stateMachineEntry.getKey());
1062 }
1063 }
1064
1065 for (String session : associatedSessions) {
1066 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1067 flushStateMachineSession(session,
1068 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
1069 }
1070 }
1071
Girish Kumar064084c2020-02-04 08:32:46 +00001072 private void flushStateMachineSession(String sessionId, String terminationReason) {
1073 StateMachine stateMachine = stateMachines.get(sessionId);
Girish Kumare5a1aa92020-02-14 14:08:54 +00001074 if (stateMachine == null) {
1075 // No active AAA sessions for this UNI port
1076 log.debug("No Active AAA Session found with Id {}", sessionId);
1077 return;
Girish Kumar064084c2020-02-04 08:32:46 +00001078 }
1079
Hardik Windlass9a09b832020-02-25 11:45:35 +00001080 authentications.remove(stateMachine.supplicantConnectpoint());
Girish Kumare5a1aa92020-02-14 14:08:54 +00001081 stateMachine.setSessionTerminateReason(terminationReason);
1082
Girish Kumar064084c2020-02-04 08:32:46 +00001083 //pushing captured machine stats to kafka
1084 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1085 aaaSupplicantStatsManager.getMachineStatsDelegate()
1086 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
1087
1088 StateMachine removed = stateMachines.remove(sessionId);
1089 if (removed != null) {
1090 StateMachine.deleteStateMachineMapping(removed);
1091 }
1092 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001093 }
Girish Kumar064084c2020-02-04 08:32:46 +00001094
Shubham Sharma4900ce62019-06-19 14:18:50 +00001095 private class ServerStatusChecker implements Runnable {
1096 @Override
1097 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001098 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001099 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001100 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001101 radiusOperationalStatusService.getRadiusOprStDelegate()
1102 .notify(new RadiusOperationalStatusEvent(
1103 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1104 radiusOperationalStatusService.
1105 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001106 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001107
1108 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001109}