blob: 82828fab01b45efd5527d28b87d9fd5f5fb75a1c [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;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070020
21import static java.util.concurrent.Executors.newFixedThreadPool;
22import static org.onlab.util.Tools.groupedThreads;
Girish Kumar064084c2020-02-04 08:32:46 +000023import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070024import static org.opencord.aaa.impl.OsgiPropertyConstants.*;
Girish Kumar064084c2020-02-04 08:32:46 +000025import static org.slf4j.LoggerFactory.getLogger;
26
27import com.google.common.collect.Sets;
28import java.net.InetAddress;
29import java.net.UnknownHostException;
30import java.nio.ByteBuffer;
31import java.util.Dictionary;
32import java.util.HashSet;
33import java.util.Arrays;
34import java.util.List;
Hardik Windlassd0b49692020-02-26 18:17:14 +000035import java.util.Map;
Girish Kumar064084c2020-02-04 08:32:46 +000036import java.util.Set;
37import java.util.Map.Entry;
38
Jonathan Hart932bedc2018-07-12 13:46:09 -070039import org.apache.commons.lang3.builder.ToStringBuilder;
Jonathan Hart4731dd92018-05-02 17:30:05 -070040import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070041import org.onlab.packet.EAP;
42import org.onlab.packet.EAPOL;
43import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070044import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070045import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070046import org.onlab.packet.RADIUS;
47import org.onlab.packet.RADIUSAttribute;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080048import org.onlab.util.KryoNamespace;
kartikey dubeye1545422019-05-22 12:53:45 +000049import org.onlab.util.Tools;
50import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070051import org.onosproject.core.ApplicationId;
52import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070053import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010054import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070055import org.onosproject.net.ConnectPoint;
56import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070057import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070058import org.onosproject.net.config.ConfigFactory;
59import org.onosproject.net.config.NetworkConfigEvent;
60import org.onosproject.net.config.NetworkConfigListener;
61import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010062import org.onosproject.net.device.DeviceEvent;
63import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010064import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070065import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070066import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070067import org.onosproject.net.packet.DefaultOutboundPacket;
68import org.onosproject.net.packet.InboundPacket;
69import org.onosproject.net.packet.OutboundPacket;
70import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070071import org.onosproject.net.packet.PacketProcessor;
72import org.onosproject.net.packet.PacketService;
Jonathan Hartc41227c2020-01-28 16:56:49 -080073import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080074import org.onosproject.store.service.ConsistentMap;
75import org.onosproject.store.service.MapEvent;
76import org.onosproject.store.service.MapEventListener;
77import org.onosproject.store.service.Serializer;
78import org.onosproject.store.service.StorageService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070079import org.opencord.aaa.AaaConfig;
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +000080import org.opencord.aaa.AaaMachineStatisticsEvent;
81import org.opencord.aaa.AaaMachineStatisticsService;
82import org.opencord.aaa.AaaSupplicantMachineStats;
Matteo Scandolocf847b82019-04-26 15:00:00 -070083import org.opencord.aaa.AuthenticationEvent;
84import org.opencord.aaa.AuthenticationEventListener;
Jonathan Hart612651f2019-11-25 09:21:43 -080085import org.opencord.aaa.AuthenticationRecord;
Matteo Scandolocf847b82019-04-26 15:00:00 -070086import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000087import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070088import org.opencord.aaa.RadiusCommunicator;
Shubham Sharma4900ce62019-06-19 14:18:50 +000089import org.opencord.aaa.RadiusOperationalStatusEvent;
90import org.opencord.aaa.RadiusOperationalStatusService;
91import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
Matteo Scandolocf847b82019-04-26 15:00:00 -070092import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000093import org.opencord.sadis.BaseInformationService;
94import org.opencord.sadis.SadisService;
95import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000096import org.osgi.service.component.ComponentContext;
Carmelo Cascone58b53292019-09-30 12:35:31 -070097import org.osgi.service.component.annotations.Activate;
Shubham Sharma4900ce62019-06-19 14:18:50 +000098import org.osgi.service.component.annotations.Component;
99import org.osgi.service.component.annotations.Deactivate;
100import org.osgi.service.component.annotations.Modified;
101import org.osgi.service.component.annotations.Reference;
102import org.osgi.service.component.annotations.ReferenceCardinality;
Ari Saha89831742015-06-26 10:31:48 -0700103import org.slf4j.Logger;
104
Shubham Sharma4900ce62019-06-19 14:18:50 +0000105import javax.crypto.Mac;
106import javax.crypto.spec.SecretKeySpec;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800107import java.util.Optional;
Jonathan Hart612651f2019-11-25 09:21:43 -0800108import java.util.concurrent.ConcurrentMap;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700109import java.util.concurrent.ExecutorService;
kartikey dubeye1545422019-05-22 12:53:45 +0000110import java.util.concurrent.Executors;
111import java.util.concurrent.ScheduledExecutorService;
112import java.util.concurrent.ScheduledFuture;
113import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000114
Ari Saha89831742015-06-26 10:31:48 -0700115/**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700116 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -0700117 */
Carmelo Cascone58b53292019-09-30 12:35:31 -0700118@Component(immediate = true, property = {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000119 OPERATIONAL_STATUS_SERVER_EVENT_GENERATION + ":Integer=" + OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT,
120 OPERATIONAL_STATUS_SERVER_TIMEOUT + ":Integer=" + OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT,
121 STATUS_SERVER_MODE + ":String=" + STATUS_SERVER_MODE_DEFAULT,
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700122 PACKET_PROCESSOR_THREADS + ":Integer=" + PACKET_PROCESSOR_THREADS_DEFAULT,
Carmelo Cascone58b53292019-09-30 12:35:31 -0700123})
Jonathan Hart5db44532018-07-12 18:13:54 -0700124public class AaaManager
125 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
126 implements AuthenticationService {
127
Charles Chandf7ff862017-01-20 11:22:05 -0800128 private static final String APP_NAME = "org.opencord.aaa";
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700129 private static final int STATE_MACHINE_THREADS = 3;
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;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700173 /**
174 * Number of threads used to process the packet.
175 */
176 protected int packetProcessorThreads = PACKET_PROCESSOR_THREADS_DEFAULT;
kartikey dubeye1545422019-05-22 12:53:45 +0000177
Jonathan Hart612651f2019-11-25 09:21:43 -0800178 private IdentifierManager idManager;
179
180 private ConcurrentMap<String, StateMachine> stateMachines;
181
Hardik Windlassd0b49692020-02-26 18:17:14 +0000182 private ConsistentMap<ConnectPoint, AuthenticationRecord> authenticationsConsistentMap;
183 private Map<ConnectPoint, AuthenticationRecord> authentications;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800184
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700185 // NAS IP address
186 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100187
188 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700189 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100190
191 // Parsed RADIUS server addresses
192 protected InetAddress radiusIpAddress;
193
194 // MAC address of RADIUS server or net hop router
195 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700196
197 // RADIUS server secret
198 protected String radiusSecret;
199
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100200 // bindings
201 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700202
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700203 // our application-specific event handler
204 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700205
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700206 // our unique identifier
207 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700208
Shubham Sharma1e43c562019-06-19 14:18:12 +0000209 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
210 protected int cleanupTimerTimeOutInMins;
211
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100212 // Setup specific customization/attributes on the RADIUS packets
213 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700214
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100215 // packet customizer to use
216 private String customizer;
217
218 // Type of connection to use to communicate with Radius server, options are
219 // "socket" or "packet_out"
220 private String radiusConnectionType;
221
Jonathan Hart5db44532018-07-12 18:13:54 -0700222 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100223 // server, socket based or packet_out based
224 RadiusCommunicator impl = null;
225
226 // latest configuration
227 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700228
Shubham Sharma4900ce62019-06-19 14:18:50 +0000229 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000230 String configuredAaaServerAddress;
Jonathan Hartc41227c2020-01-28 16:56:49 -0800231 HashSet<Byte> outPacketSet = new HashSet<>();
232 HashSet<Byte> outPacketSupp = new HashSet<>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000233 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
234 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700235 // Configuration properties factory
236 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800237 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
238 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700239 "AAA") {
240 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800241 public AaaConfig createConfig() {
242 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700243 }
244 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700245
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700246 // Listener for config changes
247 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700248
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800249 private final InternalMapEventListener mapListener = new InternalMapEventListener();
250
Jonathan Hart5db44532018-07-12 18:13:54 -0700251 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
252
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700253 protected ExecutorService packetProcessorExecutor;
254 protected ScheduledExecutorService serverStatusAndStateMachineTimeoutExecutor;
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700255 /**
256 * Builds an EAPOL packet based on the given parameters.
257 *
258 * @param dstMac destination MAC address
259 * @param srcMac source MAC address
260 * @param vlan vlan identifier
261 * @param eapolType EAPOL type
262 * @param eap EAP payload
263 * @return Ethernet frame
264 */
265 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100266 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700267
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700268 Ethernet eth = new Ethernet();
269 eth.setDestinationMACAddress(dstMac.toBytes());
270 eth.setSourceMACAddress(srcMac.toBytes());
271 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
272 if (vlan != Ethernet.VLAN_UNTAGGED) {
273 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100274 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700275 }
276 //eapol header
277 EAPOL eapol = new EAPOL();
278 eapol.setEapolType(eapolType);
279 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700280
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700281 //eap part
282 eapol.setPayload(eap);
283
284 eth.setPayload(eapol);
285 eth.setPad(true);
286 return eth;
287 }
Ari Saha89831742015-06-26 10:31:48 -0700288
Ari Saha89831742015-06-26 10:31:48 -0700289 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000290 public void activate(ComponentContext context) {
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700291
Jonathan Hart612651f2019-11-25 09:21:43 -0800292 idManager = new IdentifierManager();
293 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800294 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800295
296 KryoNamespace authSerializer = KryoNamespace.newBuilder()
Jonathan Hartc41227c2020-01-28 16:56:49 -0800297 .register(KryoNamespaces.API)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800298 .register(AuthenticationRecord.class)
299 .build();
300
Hardik Windlassd0b49692020-02-26 18:17:14 +0000301 authenticationsConsistentMap = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800302 .withApplicationId(appId)
303 .withName("authentications")
304 .withSerializer(Serializer.using(authSerializer))
305 .build();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000306 authenticationsConsistentMap.addListener(mapListener);
307 authentications = authenticationsConsistentMap.asJavaMap();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800308
Jonathan Hart5db44532018-07-12 18:13:54 -0700309 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400310 netCfgService.addListener(cfgListener);
311 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000312 cfgService.registerProperties(getClass());
313 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000314 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530315 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800316 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400317 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530318 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700319 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700320 packetService.addProcessor(processor, PacketProcessor.director(2));
Jonathan Hart5db44532018-07-12 18:13:54 -0700321 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000322 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
323 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100324 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100325 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100326 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000327 getConfiguredAaaServerAddress();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000328 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700329 serverStatusAndStateMachineTimeoutExecutor = Executors.newScheduledThreadPool(STATE_MACHINE_THREADS,
330 groupedThreads("onos/aaa", "aaa-machine-%d", log));
Shubham Sharma4900ce62019-06-19 14:18:50 +0000331
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700332 scheduledStatusServerChecker = serverStatusAndStateMachineTimeoutExecutor.scheduleAtFixedRate(
333 new ServerStatusChecker(), 0,
334 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100335
Jian Li13c67162015-12-09 13:20:34 -0800336 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700337 }
338
339 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000340 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100341 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700342 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530343 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000344 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700345 StateMachine.unsetDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100346 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100347 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700348 eventDispatcher.removeSink(AuthenticationEvent.class);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000349 scheduledStatusServerChecker.cancel(true);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700350 serverStatusAndStateMachineTimeoutExecutor.shutdown();
351 packetProcessorExecutor.shutdown();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000352 authenticationsConsistentMap.removeListener(mapListener);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800353
Jian Li13c67162015-12-09 13:20:34 -0800354 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700355 }
kartikey dubeye1545422019-05-22 12:53:45 +0000356 @Modified
357 public void modified(ComponentContext context) {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000358 Dictionary<String, Object> properties = context.getProperties();
359
Jonathan Hartc41227c2020-01-28 16:56:49 -0800360 String s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
Shubham Sharma4900ce62019-06-19 14:18:50 +0000361 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
362 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
363 : Integer.parseInt(s.trim());
364
365 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
366 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
367 : Integer.parseInt(s.trim());
368
369 s = Tools.get(properties, "operationalStatusEvaluationMode");
370 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
371
372 radiusOperationalStatusService
373 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
374 RadiusOperationalStatusEvaluationMode newEvaluationMode =
375 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
376 if (newEvaluationMode != null) {
377 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
378 operationalStatusEvaluationMode = newEvaluationModeString;
379 } else {
380 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
381 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700382
383 s = Tools.get(properties, PACKET_PROCESSOR_THREADS);
384 int oldpacketProcessorThreads = packetProcessorThreads;
385 packetProcessorThreads = Strings.isNullOrEmpty(s) ? oldpacketProcessorThreads
386 : Integer.parseInt(s.trim());
387 if (packetProcessorExecutor == null || oldpacketProcessorThreads != packetProcessorThreads) {
388 if (packetProcessorExecutor != null) {
389 packetProcessorExecutor.shutdown();
390 }
391 packetProcessorExecutor = newFixedThreadPool(packetProcessorThreads,
392 groupedThreads("onos/aaa", "aaa-packet-%d", log));
393
394 }
kartikey dubeye1545422019-05-22 12:53:45 +0000395 }
396
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000397 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530398 if (radiusConnectionType.toLowerCase().equals("socket")) {
399 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
400 } else {
401 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
402 deviceService, subsService, pktCustomizer, this);
403 }
404 }
405
406 private void configurePacketCustomizer() {
407 switch (customizer.toLowerCase()) {
408 case "sample":
409 pktCustomizer = new SamplePacketCustomizer(customInfo);
410 log.info("Created SamplePacketCustomizer");
411 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800412 case "att":
413 pktCustomizer = new AttPacketCustomizer(customInfo);
414 log.info("Created AttPacketCustomizer");
415 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530416 default:
417 pktCustomizer = new PacketCustomizer(customInfo);
418 log.info("Created default PacketCustomizer");
419 break;
420 }
421 }
422
kartikey dubeye1545422019-05-22 12:53:45 +0000423 private void getConfiguredAaaServerAddress() {
424 try {
425 InetAddress address;
426 if (newCfg.radiusHostName() != null) {
427 address = InetAddress.getByName(newCfg.radiusHostName());
428 } else {
429 address = newCfg.radiusIp();
430 }
431
432 configuredAaaServerAddress = address.getHostAddress();
433 } catch (UnknownHostException uhe) {
434 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
435 }
436 }
437
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000438 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
439 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000440 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
441 }
442 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000443
444 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
445 byte[] newHash = new byte[16];
446 Arrays.fill(newHash, (byte) 0);
447 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
448 byte[] authenticator = radiusPacket.getAuthenticator();
449 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
450 radiusPacket.setAuthenticator(requestAuthenticator);
451 // Calculate the MD5 HMAC based on the message
452 try {
453 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
454 Mac mac = Mac.getInstance("HmacMD5");
455 mac.init(keySpec);
456 newHash = mac.doFinal(radiusPacket.serialize());
457 } catch (Exception e) {
458 log.error("Failed to generate message authenticator: {}", e.getMessage());
459 }
460 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
461 radiusPacket.setAuthenticator(authenticator);
462 // Compare the calculated Message-Authenticator with the one in the message
463 return Arrays.equals(newHash, messageAuthenticator);
464 }
kartikey dubeye1545422019-05-22 12:53:45 +0000465 public void checkForPacketFromUnknownServer(String hostAddress) {
466 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000467 getConfiguredAaaServerAddress();
468 if (!hostAddress.equals(configuredAaaServerAddress)) {
469 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
470 }
kartikey dubeye1545422019-05-22 12:53:45 +0000471 }
472 }
473
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100474 /**
475 * Send RADIUS packet to the RADIUS server.
476 *
477 * @param radiusPacket RADIUS packet to be sent to server.
478 * @param inPkt Incoming EAPOL packet
479 */
480 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000481 outPacketSet.add(radiusPacket.getIdentifier());
482 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
483 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000484 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100485 impl.sendRadiusPacket(radiusPacket, inPkt);
486 }
Ray Milkey967776a2015-10-07 14:37:17 -0700487
Jonathan Hart612651f2019-11-25 09:21:43 -0800488 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100489 * Handles RADIUS packets.
490 *
491 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100492 */
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700493 public void handleRadiusPacket(RADIUS radiusPacket) {
494 packetProcessorExecutor.execute(() -> {
495 if (log.isTraceEnabled()) {
496 log.trace("Received RADIUS packet {}", radiusPacket);
497 }
498 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
499 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
500 return;
501 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800502
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700503 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
504 String sessionId = idManager.getSessionId(identifier);
Jonathan Hart612651f2019-11-25 09:21:43 -0800505
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700506 if (sessionId == null) {
507 log.error("Invalid packet identifier {}, could not find corresponding "
508 + "state machine ... exiting", radiusPacket.getIdentifier());
509 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
510 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
511 return;
512 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800513
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700514 idManager.releaseIdentifier(identifier);
515 StateMachine stateMachine = stateMachines.get(sessionId);
516 if (stateMachine == null) {
517 log.error("Invalid packet identifier {}, could not find corresponding "
518 + "state machine ... exiting", radiusPacket.getIdentifier());
519 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
520 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
521 return;
522 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000523
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700524 //instance of StateMachine using the sessionId for updating machine stats
525 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000526
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700527 EAP eapPayload;
528 Ethernet eth;
529 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000530
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700531 //increasing packets and octets received from server
532 machineStats.incrementTotalPacketsReceived();
533 try {
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000534 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700535 } catch (DeserializationException e) {
536 log.error(e.getMessage());
537 return;
538 }
539
540 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
541 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
542 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
543 }
544
545 switch (radiusPacket.getCode()) {
546 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
547 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
548 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
549 byte[] challengeState = null;
550 if (radiusAttrState != null) {
551 challengeState = radiusAttrState.getValue();
552 }
553 try {
554 eapPayload = radiusPacket.decapsulateMessage();
555 eth = buildEapolResponse(stateMachine.supplicantAddress(),
556 MacAddress.valueOf(nasMacAddress),
557 stateMachine.vlanId(),
558 EAPOL.EAPOL_PACKET,
559 eapPayload, stateMachine.priorityCode());
560 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
561 } catch (DeserializationException e) {
562 log.error(e.getMessage());
563 break;
564 }
565 log.debug("Send EAP challenge response to supplicant {}",
566 stateMachine.supplicantAddress().toString());
567 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
568 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
569 outPacketSupp.add(eapPayload.getIdentifier());
570 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
571 //increasing packets send to server
572 machineStats.incrementTotalPacketsSent();
573 machineStats.incrementTotalOctetSent(eapPayload.getLength());
574 break;
575 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
576 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
577 //send an EAPOL - Success to the supplicant.
578 byte[] eapMessageSuccess =
579 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
580 try {
581 eapPayload = EAP.deserializer().deserialize(
582 eapMessageSuccess, 0, eapMessageSuccess.length);
583 } catch (DeserializationException e) {
584 log.error(e.getMessage());
585 break;
586 }
587
588 eth = buildEapolResponse(stateMachine.supplicantAddress(),
589 MacAddress.valueOf(nasMacAddress),
590 stateMachine.vlanId(),
591 EAPOL.EAPOL_PACKET,
592 eapPayload, stateMachine.priorityCode());
593 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
594 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
595 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
596
597 stateMachine.authorizeAccess();
598 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
599 //increasing packets send to server
600 machineStats.incrementTotalPacketsSent();
601 machineStats.incrementTotalOctetSent(eapPayload.getLength());
602 break;
603 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
604 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
605 //send an EAPOL - Failure to the supplicant.
606 byte[] eapMessageFailure;
607 eapPayload = new EAP();
608 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
609 if (radiusAttrEap == null) {
610 eapPayload.setCode(EAP.FAILURE);
611 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
612 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
613 } else {
614 eapMessageFailure = radiusAttrEap.getValue();
615 try {
616 eapPayload = EAP.deserializer().deserialize(
617 eapMessageFailure, 0, eapMessageFailure.length);
618 } catch (DeserializationException e) {
619 log.error(e.getMessage());
620 break;
621 }
622 }
623 eth = buildEapolResponse(stateMachine.supplicantAddress(),
624 MacAddress.valueOf(nasMacAddress),
625 stateMachine.vlanId(),
626 EAPOL.EAPOL_PACKET,
627 eapPayload, stateMachine.priorityCode());
628 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
629 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
630 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
631
632 stateMachine.denyAccess();
633 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
634 //increasing packets send to server
635 machineStats.incrementTotalPacketsSent();
636 machineStats.incrementTotalOctetSent(eapPayload.getLength());
637 //pushing machine stats to kafka
638 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
639 aaaSupplicantStatsManager.getMachineStatsDelegate()
640 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE,
641 machineObj));
642 break;
643 default:
644 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
645 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
646 //increasing packets received to server
647 machineStats.incrementTotalPacketsReceived();
648 try {
649 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
650 } catch (DeserializationException e) {
651 log.error(e.getMessage());
652 break;
653 }
654 }
655 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
656 });
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700657 }
658
Ray Milkey967776a2015-10-07 14:37:17 -0700659 /**
660 * Send the ethernet packet to the supplicant.
661 *
662 * @param ethernetPkt the ethernet packet
663 * @param connectPoint the connect point to send out
664 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000665 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700666 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
667 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
668 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000669 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700670 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700671 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
672 eap, ethernetPkt, connectPoint);
673 }
Ray Milkey967776a2015-10-07 14:37:17 -0700674 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000675 if (isChallengeResponse) {
676 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
677 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000678 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
679 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700680 }
681
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400682 @Override
683 public String toString() {
684 return ToStringBuilder.reflectionToString(this);
685 }
686
Jonathan Hart612651f2019-11-25 09:21:43 -0800687 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800688 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
Hardik Windlassd0b49692020-02-26 18:17:14 +0000689 return authentications.values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800690 }
691
692 @Override
693 public boolean removeAuthenticationStateByMac(MacAddress mac) {
694
Hardik Windlassd0b49692020-02-26 18:17:14 +0000695 Optional<AuthenticationRecord> r = authentications.values().stream()
696 .filter(v -> v.supplicantAddress().equals(mac))
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800697 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800698
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800699 if (r.isEmpty()) {
700 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800701 }
702
Hardik Windlassd0b49692020-02-26 18:17:14 +0000703 AuthenticationRecord removed =
704 authentications.remove(r.get().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800705
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800706 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800707 }
708
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800709 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800710 return stateMachines.get(sessionId);
711 }
712
713 private String sessionId(ConnectPoint cp) {
714 return cp.deviceId().toString() + cp.port().toString();
715 }
716
Ari Saha89831742015-06-26 10:31:48 -0700717 // our handler defined as a private inner class
718
719 /**
720 * Packet processor responsible for forwarding packets along their paths.
721 */
722 private class ReactivePacketProcessor implements PacketProcessor {
723 @Override
724 public void process(PacketContext context) {
725
726 // Extract the original Ethernet frame from the packet information
727 InboundPacket pkt = context.inPacket();
728 Ethernet ethPkt = pkt.parsed();
729 if (ethPkt == null) {
730 return;
731 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100732
Jonathan Hart612651f2019-11-25 09:21:43 -0800733 // identify if incoming packet comes from supplicant (EAP) or RADIUS
734 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
735 case EAPOL:
736 handleSupplicantPacket(context.inPacket());
737 break;
738 default:
739 // any other packets let the specific implementation handle
740 impl.handlePacketFromServer(context);
Ari Saha89831742015-06-26 10:31:48 -0700741 }
742 }
743
Ray Milkey9eb293f2015-09-30 15:09:17 -0700744 /**
745 * Creates and initializes common fields of a RADIUS packet.
746 *
Ray Milkey967776a2015-10-07 14:37:17 -0700747 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700748 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700749 * @return RADIUS packet
750 */
Ray Milkey967776a2015-10-07 14:37:17 -0700751 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700752 RADIUS radiusPayload =
753 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
754 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700755
756 // set Request Authenticator in StateMachine
757 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
758
Ray Milkey9eb293f2015-09-30 15:09:17 -0700759 radiusPayload.setIdentifier(identifier);
760 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700761 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700762
763 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800764 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700765
766 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700767
768 return radiusPayload;
769 }
Ari Saha89831742015-06-26 10:31:48 -0700770
771 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700772 * Handles PAE packets (supplicant).
773 *
774 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700775 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800776 private void handleSupplicantPacket(InboundPacket inPacket) {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700777 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700778 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800779 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700780
Jonathan Harta46dddf2015-06-30 15:31:20 -0700781 DeviceId deviceId = inPacket.receivedFrom().deviceId();
782 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800783 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700784 EAPOL eapol = (EAPOL) ethPkt.getPayload();
785 if (log.isTraceEnabled()) {
786 log.trace("Received EAPOL packet {} in enclosing packet {} from "
787 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
788 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100789 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700790
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000791 short pktlen = eapol.getPacketLength();
792 byte[] eapPayLoadBuffer = eapol.serialize();
793 int len = eapPayLoadBuffer.length;
794 if (len != (HEADER_LENGTH + pktlen)) {
795 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
796 return;
797 }
798 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
799 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
800 return;
801 }
802 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
803 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
804 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800805
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700806 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id ->
807 new StateMachine(id, serverStatusAndStateMachineTimeoutExecutor));
Jonathan Hart612651f2019-11-25 09:21:43 -0800808 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700809
Ari Saha89831742015-06-26 10:31:48 -0700810 switch (eapol.getEapolType()) {
811 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400812 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700813 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800814 stateMachine.setSupplicantAddress(srcMac);
Jonathan Hart5db44532018-07-12 18:13:54 -0700815 stateMachine.start();
Jonathan Hart612651f2019-11-25 09:21:43 -0800816
Shubham Sharma1f193582019-07-11 12:12:41 +0000817 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700818 //send an EAP Request/Identify to the supplicant
819 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100820 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
821 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
822 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800823 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700824 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100825 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400826
Ray Milkeyf51eba22015-09-25 10:24:23 -0700827 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400828 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000829 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000830 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
Ari Saha89831742015-06-26 10:31:48 -0700831
832 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800833 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400834 log.debug("EAP packet: EAPOL_LOGOFF");
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000835 //posting the machine stat data for current supplicant device.
836 if (stateMachine.getSessionTerminateReason() == null ||
837 stateMachine.getSessionTerminateReason().equals("")) {
838 stateMachine.setSessionTerminateReason(
839 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
840 }
841 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
842 aaaSupplicantStatsManager.getMachineStatsDelegate()
843 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Ray Milkeyb34b4962016-01-04 10:24:43 -0800844 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
845 stateMachine.logoff();
Shubham Sharma1f193582019-07-11 12:12:41 +0000846 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800847 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000848 if (stateMachine.state() == StateMachine.STATE_IDLE) {
849 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
850 }
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800851
852 break;
Ari Saha89831742015-06-26 10:31:48 -0700853 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700854 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700855 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700856 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000857 Byte identifier = new Byte(eapPacket.getIdentifier());
Ari Saha89831742015-06-26 10:31:48 -0700858
Jonathan Hart612651f2019-11-25 09:21:43 -0800859 // get identifier for request and store mapping to session ID
860 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
861
Ari Saha89831742015-06-26 10:31:48 -0700862 byte dataType = eapPacket.getDataType();
863 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700864
Ray Milkey9eb293f2015-09-30 15:09:17 -0700865 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400866 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharma1e43c562019-06-19 14:18:12 +0000867 //Setting the time of this response from RG, only when its not a re-transmission.
868 if (stateMachine.getLastPacketReceivedTime() == 0) {
869 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
870 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700871 // request id access to RADIUS
872 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700873
Jonathan Hart612651f2019-11-25 09:21:43 -0800874 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100875 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800876 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700877
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().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700881 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000882 if (stateMachine.state() == StateMachine.STATE_PENDING) {
883 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000884 stateMachine.incrementTotalPacketsSent();
885 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
kartikey dubeye1545422019-05-22 12:53:45 +0000886 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700887 stateMachine.requestAccess();
888 break;
Ari Saha89831742015-06-26 10:31:48 -0700889 case EAP.ATTR_MD5:
Shubham Sharma1e43c562019-06-19 14:18:12 +0000890 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400891 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700892 // verify if the EAP identifier corresponds to the
893 // challenge identifier from the client state
894 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700895 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700896 //send the RADIUS challenge response
Jonathan Hart612651f2019-11-25 09:21:43 -0800897 radiusPayload = getRadiusPayload(stateMachine,
898 radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100899 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700900
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800901 if (stateMachine.challengeState() != null) {
902 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
903 stateMachine.challengeState());
904 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800905 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000906 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
907 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
908 outPacketSupp.remove(identifier);
909 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100910 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000911 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000912 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700913 }
914 break;
915 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400916 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700917 // request id access to RADIUS
Jonathan Hart612651f2019-11-25 09:21:43 -0800918 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100919 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700920
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800921 if (stateMachine.challengeState() != null) {
922 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
923 stateMachine.challengeState());
924 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700925 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700926
Jonathan Hart092dfb22015-11-16 23:05:21 -0800927 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000928 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
929 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
930 outPacketSupp.remove(identifier);
931 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100932 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000933 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000934 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700935
Ray Milkeyf3790b82015-10-21 16:28:08 -0700936 if (stateMachine.state() != StateMachine.STATE_PENDING) {
937 stateMachine.requestAccess();
938 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700939
Ari Saha89831742015-06-26 10:31:48 -0700940 break;
941 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400942 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700943 return;
944 }
945 break;
946 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400947 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700948 }
Shubham Sharma1f193582019-07-11 12:12:41 +0000949 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
950 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700951 }
Ray Milkey967776a2015-10-07 14:37:17 -0700952 }
953
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100954 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700955 * Delegate allowing the StateMachine to notify us of events.
956 */
957 private class InternalStateMachineDelegate implements StateMachineDelegate {
958
959 @Override
960 public void notify(AuthenticationEvent authenticationEvent) {
961 log.info("Auth event {} for {}",
962 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -0800963
964 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
965 handleStateMachineTimeout(authenticationEvent.subject());
966 }
967
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800968 AuthenticationRecord record = authenticationEvent.authenticationRecord();
969 if (record == null) {
970 authentications.remove(authenticationEvent.subject());
971 } else {
972 authentications.put(authenticationEvent.subject(), record);
973 }
974
Jonathan Hart5db44532018-07-12 18:13:54 -0700975 post(authenticationEvent);
976 }
977 }
978
Jonathan Hart612651f2019-11-25 09:21:43 -0800979 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
980 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
Andrea Campanellae66466a2020-02-03 14:05:45 +0000981 //pushing captured machine stats to kafka
982 stateMachine.setSessionTerminateReason("Time out");
983 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
984 .getSupplicantStats(stateMachine);
985 aaaSupplicantStatsManager.getMachineStatsDelegate()
986 .notify(new AaaMachineStatisticsEvent(
987 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
988
Jonathan Hart612651f2019-11-25 09:21:43 -0800989 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
990 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
991 }
992
993 StateMachine.deleteStateMachineMapping(stateMachine);
994 }
995
Jonathan Hart5db44532018-07-12 18:13:54 -0700996 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100997 * Configuration Listener, handles change in configuration.
998 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700999 private class InternalConfigListener implements NetworkConfigListener {
1000
1001 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -08001002 * Reconfigures the AAA application according to the
1003 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001004 *
1005 * @param cfg configuration object
1006 */
Jonathan Hart092dfb22015-11-16 23:05:21 -08001007 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001008 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001009
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001010 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -08001011 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001012 } else {
1013 newCfg = cfg;
1014 }
1015 if (newCfg.nasIp() != null) {
1016 nasIpAddress = newCfg.nasIp();
1017 }
1018 if (newCfg.radiusIp() != null) {
1019 radiusIpAddress = newCfg.radiusIp();
1020 }
1021 if (newCfg.radiusMac() != null) {
1022 radiusMacAddress = newCfg.radiusMac();
1023 }
1024 if (newCfg.nasMac() != null) {
1025 nasMacAddress = newCfg.nasMac();
1026 }
1027 if (newCfg.radiusSecret() != null) {
1028 radiusSecret = newCfg.radiusSecret();
1029 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001030
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301031 boolean reconfigureCustomizer = false;
1032 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
1033 customizer = newCfg.radiusPktCustomizer();
1034 configurePacketCustomizer();
1035 reconfigureCustomizer = true;
1036 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001037
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301038 if (radiusConnectionType == null
1039 || reconfigureCustomizer
1040 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
1041 radiusConnectionType = newCfg.radiusConnectionType();
1042 if (impl != null) {
1043 impl.withdrawIntercepts();
1044 impl.clearLocalState();
1045 }
1046 configureRadiusCommunication();
1047 impl.initializeLocalState(newCfg);
1048 impl.requestIntercepts();
1049 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001050 impl.clearLocalState();
1051 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -07001052 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001053 }
1054
1055 @Override
1056 public void event(NetworkConfigEvent event) {
1057
1058 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1059 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001060 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001061
Jonathan Hart092dfb22015-11-16 23:05:21 -08001062 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001063 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001064
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001065 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001066 }
1067 }
1068 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001069
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001070 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1071 @Override
1072 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1073 if (event.type() == MapEvent.Type.REMOVE) {
1074 // remove local state machine if user has requested remove
1075 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1076 if (sm != null) {
1077 sm.stop();
1078 }
1079 }
1080 }
1081 }
1082
Amit Ghoshf739be52017-09-21 15:49:37 +01001083 private class InternalDeviceListener implements DeviceListener {
1084 @Override
1085 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001086 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001087 switch (event.type()) {
1088 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001089 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001090 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001091 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
Hardik Windlass75c67712020-02-21 10:57:20 +00001092
Girish Kumar064084c2020-02-04 08:32:46 +00001093 flushStateMachineSession(sessionId,
1094 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001095
Girish Kumar064084c2020-02-04 08:32:46 +00001096 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001097 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001098 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001099 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001100 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001101
Amit Ghoshf739be52017-09-21 15:49:37 +01001102 default:
1103 return;
1104 }
1105 }
Girish Kumar064084c2020-02-04 08:32:46 +00001106
Andrea Campanellabba33672020-02-11 14:03:01 +01001107 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1108 Set<String> associatedSessions = Sets.newHashSet();
1109 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1110 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1111 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1112 associatedSessions.add(stateMachineEntry.getKey());
1113 }
1114 }
1115
1116 for (String session : associatedSessions) {
1117 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1118 flushStateMachineSession(session,
1119 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
1120 }
1121 }
1122
Girish Kumar064084c2020-02-04 08:32:46 +00001123 private void flushStateMachineSession(String sessionId, String terminationReason) {
1124 StateMachine stateMachine = stateMachines.get(sessionId);
Girish Kumare5a1aa92020-02-14 14:08:54 +00001125 if (stateMachine == null) {
1126 // No active AAA sessions for this UNI port
1127 log.debug("No Active AAA Session found with Id {}", sessionId);
1128 return;
Girish Kumar064084c2020-02-04 08:32:46 +00001129 }
1130
Hardik Windlass9a09b832020-02-25 11:45:35 +00001131 authentications.remove(stateMachine.supplicantConnectpoint());
Girish Kumare5a1aa92020-02-14 14:08:54 +00001132 stateMachine.setSessionTerminateReason(terminationReason);
1133
Girish Kumar064084c2020-02-04 08:32:46 +00001134 //pushing captured machine stats to kafka
1135 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1136 aaaSupplicantStatsManager.getMachineStatsDelegate()
1137 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Girish Kumar064084c2020-02-04 08:32:46 +00001138 StateMachine removed = stateMachines.remove(sessionId);
Shubham Sharma8d7a9822020-01-28 10:04:01 +00001139
Girish Kumar064084c2020-02-04 08:32:46 +00001140 if (removed != null) {
1141 StateMachine.deleteStateMachineMapping(removed);
1142 }
1143 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001144 }
Girish Kumar064084c2020-02-04 08:32:46 +00001145
Shubham Sharma4900ce62019-06-19 14:18:50 +00001146 private class ServerStatusChecker implements Runnable {
1147 @Override
1148 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001149 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001150 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001151 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001152 radiusOperationalStatusService.getRadiusOprStDelegate()
1153 .notify(new RadiusOperationalStatusEvent(
1154 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1155 radiusOperationalStatusService.
1156 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001157 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001158
1159 }
Shubham Sharma544ffa22020-02-13 06:41:02 +00001160
1161 @Override
1162 public AaaSupplicantMachineStats getSupplicantMachineStats(String sessionId) {
1163 StateMachine aaaSupplicantMachine = stateMachines.get(sessionId);
1164 if (aaaSupplicantMachine != null) {
1165 return aaaSupplicantStatsManager.getSupplicantStats(aaaSupplicantMachine);
1166 } else {
1167 return null;
1168 }
1169 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001170}