blob: 56c39128198021494b7a345af9b3e4e32246d0aa [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
Andrea Campanellac4781e62020-10-08 12:58:45 +020021import static java.util.concurrent.Executors.newSingleThreadExecutor;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070022import 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;
Matteo Scandoloe033c262020-10-14 11:37:39 -070028
Girish Kumar064084c2020-02-04 08:32:46 +000029import java.net.InetAddress;
30import java.net.UnknownHostException;
31import java.nio.ByteBuffer;
32import java.util.Dictionary;
33import java.util.HashSet;
34import java.util.Arrays;
35import java.util.List;
Hardik Windlassd0b49692020-02-26 18:17:14 +000036import java.util.Map;
Girish Kumar064084c2020-02-04 08:32:46 +000037import java.util.Set;
38import java.util.Map.Entry;
39
Jonathan Hart932bedc2018-07-12 13:46:09 -070040import org.apache.commons.lang3.builder.ToStringBuilder;
Jonathan Hart4731dd92018-05-02 17:30:05 -070041import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070042import org.onlab.packet.EAP;
43import org.onlab.packet.EAPOL;
44import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070045import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070046import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070047import org.onlab.packet.RADIUS;
48import org.onlab.packet.RADIUSAttribute;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080049import org.onlab.util.KryoNamespace;
kartikey dubeye1545422019-05-22 12:53:45 +000050import org.onlab.util.Tools;
51import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070052import org.onosproject.core.ApplicationId;
53import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070054import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010055import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070056import org.onosproject.net.ConnectPoint;
57import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070058import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070059import org.onosproject.net.config.ConfigFactory;
60import org.onosproject.net.config.NetworkConfigEvent;
61import org.onosproject.net.config.NetworkConfigListener;
62import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010063import org.onosproject.net.device.DeviceEvent;
64import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010065import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070066import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070067import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070068import org.onosproject.net.packet.DefaultOutboundPacket;
69import org.onosproject.net.packet.InboundPacket;
70import org.onosproject.net.packet.OutboundPacket;
71import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070072import org.onosproject.net.packet.PacketProcessor;
73import org.onosproject.net.packet.PacketService;
Jonathan Hartc41227c2020-01-28 16:56:49 -080074import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080075import org.onosproject.store.service.ConsistentMap;
76import org.onosproject.store.service.MapEvent;
77import org.onosproject.store.service.MapEventListener;
78import org.onosproject.store.service.Serializer;
79import org.onosproject.store.service.StorageService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070080import org.opencord.aaa.AaaConfig;
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +000081import org.opencord.aaa.AaaMachineStatisticsEvent;
82import org.opencord.aaa.AaaMachineStatisticsService;
83import org.opencord.aaa.AaaSupplicantMachineStats;
Matteo Scandolocf847b82019-04-26 15:00:00 -070084import org.opencord.aaa.AuthenticationEvent;
85import org.opencord.aaa.AuthenticationEventListener;
Jonathan Hart612651f2019-11-25 09:21:43 -080086import org.opencord.aaa.AuthenticationRecord;
Matteo Scandolocf847b82019-04-26 15:00:00 -070087import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000088import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070089import org.opencord.aaa.RadiusCommunicator;
Shubham Sharma4900ce62019-06-19 14:18:50 +000090import org.opencord.aaa.RadiusOperationalStatusEvent;
91import org.opencord.aaa.RadiusOperationalStatusService;
92import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
Matteo Scandolocf847b82019-04-26 15:00:00 -070093import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000094import org.opencord.sadis.BaseInformationService;
95import org.opencord.sadis.SadisService;
96import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000097import org.osgi.service.component.ComponentContext;
Carmelo Cascone58b53292019-09-30 12:35:31 -070098import org.osgi.service.component.annotations.Activate;
Shubham Sharma4900ce62019-06-19 14:18:50 +000099import org.osgi.service.component.annotations.Component;
100import org.osgi.service.component.annotations.Deactivate;
101import org.osgi.service.component.annotations.Modified;
102import org.osgi.service.component.annotations.Reference;
103import org.osgi.service.component.annotations.ReferenceCardinality;
Ari Saha89831742015-06-26 10:31:48 -0700104import org.slf4j.Logger;
105
Shubham Sharma4900ce62019-06-19 14:18:50 +0000106import javax.crypto.Mac;
107import javax.crypto.spec.SecretKeySpec;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800108import java.util.Optional;
Jonathan Hart612651f2019-11-25 09:21:43 -0800109import java.util.concurrent.ConcurrentMap;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700110import java.util.concurrent.ExecutorService;
kartikey dubeye1545422019-05-22 12:53:45 +0000111import java.util.concurrent.Executors;
112import java.util.concurrent.ScheduledExecutorService;
113import java.util.concurrent.ScheduledFuture;
114import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000115
Ari Saha89831742015-06-26 10:31:48 -0700116/**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700117 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -0700118 */
Carmelo Cascone58b53292019-09-30 12:35:31 -0700119@Component(immediate = true, property = {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000120 OPERATIONAL_STATUS_SERVER_EVENT_GENERATION + ":Integer=" + OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT,
121 OPERATIONAL_STATUS_SERVER_TIMEOUT + ":Integer=" + OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT,
122 STATUS_SERVER_MODE + ":String=" + STATUS_SERVER_MODE_DEFAULT,
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700123 PACKET_PROCESSOR_THREADS + ":Integer=" + PACKET_PROCESSOR_THREADS_DEFAULT,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700124 FORGE_EAPOL_PACKETS + ":Boolean=" + FORGE_EAPOL_PACKETS_DEFAULT,
Carmelo Cascone58b53292019-09-30 12:35:31 -0700125})
Jonathan Hart5db44532018-07-12 18:13:54 -0700126public class AaaManager
127 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
128 implements AuthenticationService {
129
Charles Chandf7ff862017-01-20 11:22:05 -0800130 private static final String APP_NAME = "org.opencord.aaa";
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700131 private static final int STATE_MACHINE_THREADS = 3;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700132
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700133 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700134
Carmelo Cascone58b53292019-09-30 12:35:31 -0700135 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700136 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700137
Carmelo Cascone58b53292019-09-30 12:35:31 -0700138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800139 protected StorageService storageService;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700142 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700143
Carmelo Cascone58b53292019-09-30 12:35:31 -0700144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700145 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700146
Carmelo Cascone58b53292019-09-30 12:35:31 -0700147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100148 protected DeviceService deviceService;
149
Carmelo Cascone58b53292019-09-30 12:35:31 -0700150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000151 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100152
Carmelo Cascone58b53292019-09-30 12:35:31 -0700153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100154 protected MastershipService mastershipService;
155
Carmelo Cascone58b53292019-09-30 12:35:31 -0700156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000157 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000158
Carmelo Cascone58b53292019-09-30 12:35:31 -0700159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000160 protected AaaMachineStatisticsService aaaSupplicantStatsManager;
161
162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000163 protected ComponentConfigService cfgService;
164
Shubham Sharma4900ce62019-06-19 14:18:50 +0000165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
166 protected RadiusOperationalStatusService radiusOperationalStatusService;
167
kartikey dubeye1545422019-05-22 12:53:45 +0000168 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100169 private final DeviceListener deviceListener = new InternalDeviceListener();
170
Shubham Sharma4900ce62019-06-19 14:18:50 +0000171 // Properties
Shubham Sharma4900ce62019-06-19 14:18:50 +0000172 private int operationalStatusEventGenerationPeriodInSeconds = OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
173 private int operationalStatusServerTimeoutInSeconds = OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
174 protected String operationalStatusEvaluationMode = STATUS_SERVER_MODE_DEFAULT;
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700175
176 /**
177 * If set to true the RADIUS server won't be involved in authentication.
178 **/
179 private Boolean forgeEapolPackets = FORGE_EAPOL_PACKETS_DEFAULT;
180
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700181 /**
182 * Number of threads used to process the packet.
183 */
184 protected int packetProcessorThreads = PACKET_PROCESSOR_THREADS_DEFAULT;
kartikey dubeye1545422019-05-22 12:53:45 +0000185
Jonathan Hart612651f2019-11-25 09:21:43 -0800186 private IdentifierManager idManager;
187
188 private ConcurrentMap<String, StateMachine> stateMachines;
189
Hardik Windlassd0b49692020-02-26 18:17:14 +0000190 private ConsistentMap<ConnectPoint, AuthenticationRecord> authenticationsConsistentMap;
Matteo Scandolo120d40b2020-11-25 15:49:22 -0800191 // NOTE consider to change this map to be Map<DeviceId,Map<ConnectPoint, AuthenticationRecord>> so that
192 // we can iterate on smalled collection when dealing with authentications
Hardik Windlassd0b49692020-02-26 18:17:14 +0000193 private Map<ConnectPoint, AuthenticationRecord> authentications;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800194
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700195 // NAS IP address
196 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100197
198 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700199 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100200
201 // Parsed RADIUS server addresses
202 protected InetAddress radiusIpAddress;
203
204 // MAC address of RADIUS server or net hop router
205 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700206
207 // RADIUS server secret
208 protected String radiusSecret;
209
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100210 // bindings
211 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700212
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700213 // our application-specific event handler
214 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700215
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700216 // our unique identifier
217 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700218
Shubham Sharma1e43c562019-06-19 14:18:12 +0000219 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
220 protected int cleanupTimerTimeOutInMins;
221
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100222 // Setup specific customization/attributes on the RADIUS packets
223 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700224
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100225 // packet customizer to use
226 private String customizer;
227
228 // Type of connection to use to communicate with Radius server, options are
229 // "socket" or "packet_out"
230 private String radiusConnectionType;
231
Jonathan Hart5db44532018-07-12 18:13:54 -0700232 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100233 // server, socket based or packet_out based
234 RadiusCommunicator impl = null;
235
236 // latest configuration
237 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700238
Shubham Sharma4900ce62019-06-19 14:18:50 +0000239 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000240 String configuredAaaServerAddress;
Jonathan Hartc41227c2020-01-28 16:56:49 -0800241 HashSet<Byte> outPacketSet = new HashSet<>();
242 HashSet<Byte> outPacketSupp = new HashSet<>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000243 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
244 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700245 // Configuration properties factory
246 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800247 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700248 AaaConfig.class,
249 "AAA") {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700250 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800251 public AaaConfig createConfig() {
252 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700253 }
254 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700255
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700256 // Listener for config changes
257 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700258
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800259 private final InternalMapEventListener mapListener = new InternalMapEventListener();
260
Jonathan Hart5db44532018-07-12 18:13:54 -0700261 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
262
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700263 protected ExecutorService packetProcessorExecutor;
264 protected ScheduledExecutorService serverStatusAndStateMachineTimeoutExecutor;
Matteo Scandoloe033c262020-10-14 11:37:39 -0700265
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700266 /**
267 * Builds an EAPOL packet based on the given parameters.
268 *
269 * @param dstMac destination MAC address
270 * @param srcMac source MAC address
271 * @param vlan vlan identifier
272 * @param eapolType EAPOL type
273 * @param eap EAP payload
274 * @return Ethernet frame
275 */
276 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100277 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700278
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700279 Ethernet eth = new Ethernet();
280 eth.setDestinationMACAddress(dstMac.toBytes());
281 eth.setSourceMACAddress(srcMac.toBytes());
282 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
283 if (vlan != Ethernet.VLAN_UNTAGGED) {
284 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100285 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700286 }
287 //eapol header
288 EAPOL eapol = new EAPOL();
289 eapol.setEapolType(eapolType);
290 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700291
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700292 //eap part
293 eapol.setPayload(eap);
294
295 eth.setPayload(eapol);
296 eth.setPad(true);
297 return eth;
298 }
Ari Saha89831742015-06-26 10:31:48 -0700299
Ari Saha89831742015-06-26 10:31:48 -0700300 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000301 public void activate(ComponentContext context) {
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700302
Jonathan Hart612651f2019-11-25 09:21:43 -0800303 idManager = new IdentifierManager();
304 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800305 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800306
307 KryoNamespace authSerializer = KryoNamespace.newBuilder()
Jonathan Hartc41227c2020-01-28 16:56:49 -0800308 .register(KryoNamespaces.API)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800309 .register(AuthenticationRecord.class)
310 .build();
311
Hardik Windlassd0b49692020-02-26 18:17:14 +0000312 authenticationsConsistentMap = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800313 .withApplicationId(appId)
314 .withName("authentications")
315 .withSerializer(Serializer.using(authSerializer))
316 .build();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000317 authenticationsConsistentMap.addListener(mapListener);
318 authentications = authenticationsConsistentMap.asJavaMap();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800319
Jonathan Hart5db44532018-07-12 18:13:54 -0700320 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400321 netCfgService.addListener(cfgListener);
322 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000323 cfgService.registerProperties(getClass());
324 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000325 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530326 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800327 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400328 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530329 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700330 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700331 packetService.addProcessor(processor, PacketProcessor.director(2));
Jonathan Hart5db44532018-07-12 18:13:54 -0700332 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000333 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
334 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100335 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100336 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100337 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000338 getConfiguredAaaServerAddress();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000339 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700340 serverStatusAndStateMachineTimeoutExecutor = Executors.newScheduledThreadPool(STATE_MACHINE_THREADS,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700341 groupedThreads("onos/aaa", "machine-%d", log));
Shubham Sharma4900ce62019-06-19 14:18:50 +0000342
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700343 scheduledStatusServerChecker = serverStatusAndStateMachineTimeoutExecutor.scheduleAtFixedRate(
344 new ServerStatusChecker(), 0,
345 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100346
Jian Li13c67162015-12-09 13:20:34 -0800347 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700348 }
349
350 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000351 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100352 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700353 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530354 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000355 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700356 StateMachine.unsetDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100357 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100358 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700359 eventDispatcher.removeSink(AuthenticationEvent.class);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000360 scheduledStatusServerChecker.cancel(true);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700361 serverStatusAndStateMachineTimeoutExecutor.shutdown();
362 packetProcessorExecutor.shutdown();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000363 authenticationsConsistentMap.removeListener(mapListener);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800364
Jian Li13c67162015-12-09 13:20:34 -0800365 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700366 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700367
kartikey dubeye1545422019-05-22 12:53:45 +0000368 @Modified
369 public void modified(ComponentContext context) {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000370 Dictionary<String, Object> properties = context.getProperties();
371
Jonathan Hartc41227c2020-01-28 16:56:49 -0800372 String s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
Shubham Sharma4900ce62019-06-19 14:18:50 +0000373 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
374 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
Matteo Scandoloe033c262020-10-14 11:37:39 -0700375 : Integer.parseInt(s.trim());
Shubham Sharma4900ce62019-06-19 14:18:50 +0000376
377 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
378 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
379 : Integer.parseInt(s.trim());
380
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700381 Boolean p = Tools.isPropertyEnabled(properties, FORGE_EAPOL_PACKETS);
382 forgeEapolPackets = (p == null) ? FORGE_EAPOL_PACKETS_DEFAULT : p;
383
Shubham Sharma4900ce62019-06-19 14:18:50 +0000384 s = Tools.get(properties, "operationalStatusEvaluationMode");
385 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
386
387 radiusOperationalStatusService
Matteo Scandoloe033c262020-10-14 11:37:39 -0700388 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000389 RadiusOperationalStatusEvaluationMode newEvaluationMode =
390 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
391 if (newEvaluationMode != null) {
392 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
393 operationalStatusEvaluationMode = newEvaluationModeString;
394 } else {
395 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
396 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700397
398 s = Tools.get(properties, PACKET_PROCESSOR_THREADS);
399 int oldpacketProcessorThreads = packetProcessorThreads;
400 packetProcessorThreads = Strings.isNullOrEmpty(s) ? oldpacketProcessorThreads
401 : Integer.parseInt(s.trim());
402 if (packetProcessorExecutor == null || oldpacketProcessorThreads != packetProcessorThreads) {
403 if (packetProcessorExecutor != null) {
404 packetProcessorExecutor.shutdown();
405 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700406 packetProcessorExecutor = newSingleThreadExecutor(
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700407 groupedThreads("onos/aaa", "packet-%d", log));
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700408 }
kartikey dubeye1545422019-05-22 12:53:45 +0000409 }
410
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000411 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530412 if (radiusConnectionType.toLowerCase().equals("socket")) {
413 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
414 } else {
415 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700416 deviceService, subsService, pktCustomizer, this);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530417 }
418 }
419
420 private void configurePacketCustomizer() {
421 switch (customizer.toLowerCase()) {
422 case "sample":
423 pktCustomizer = new SamplePacketCustomizer(customInfo);
424 log.info("Created SamplePacketCustomizer");
425 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800426 case "att":
427 pktCustomizer = new AttPacketCustomizer(customInfo);
428 log.info("Created AttPacketCustomizer");
429 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530430 default:
431 pktCustomizer = new PacketCustomizer(customInfo);
432 log.info("Created default PacketCustomizer");
433 break;
434 }
435 }
436
kartikey dubeye1545422019-05-22 12:53:45 +0000437 private void getConfiguredAaaServerAddress() {
438 try {
439 InetAddress address;
440 if (newCfg.radiusHostName() != null) {
441 address = InetAddress.getByName(newCfg.radiusHostName());
442 } else {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700443 address = newCfg.radiusIp();
kartikey dubeye1545422019-05-22 12:53:45 +0000444 }
445
446 configuredAaaServerAddress = address.getHostAddress();
447 } catch (UnknownHostException uhe) {
448 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
449 }
450 }
451
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000452 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
453 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000454 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
455 }
456 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000457
458 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
459 byte[] newHash = new byte[16];
460 Arrays.fill(newHash, (byte) 0);
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700461 // looking for the attributes - exit if there are no such attributes
462 if (radiusPacket.getAttributeList(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).isEmpty()) {
463 log.warn("Empty Attribute List for packet {} with identifier {}",
464 radiusPacket, radiusPacket.getIdentifier());
465 return false;
466 }
467 // get the attribute - further verify if it is null or not (not really needed)
468 RADIUSAttribute attribute = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH);
469 if (attribute == null) {
470 log.warn("Null Message Authenticator for packet {} with identifier {}",
471 radiusPacket, radiusPacket.getIdentifier());
472 return false;
473 }
474 byte[] messageAuthenticator = attribute.getValue();
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000475 byte[] authenticator = radiusPacket.getAuthenticator();
476 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
477 radiusPacket.setAuthenticator(requestAuthenticator);
478 // Calculate the MD5 HMAC based on the message
479 try {
480 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
481 Mac mac = Mac.getInstance("HmacMD5");
482 mac.init(keySpec);
483 newHash = mac.doFinal(radiusPacket.serialize());
484 } catch (Exception e) {
485 log.error("Failed to generate message authenticator: {}", e.getMessage());
486 }
487 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
488 radiusPacket.setAuthenticator(authenticator);
489 // Compare the calculated Message-Authenticator with the one in the message
490 return Arrays.equals(newHash, messageAuthenticator);
491 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700492
kartikey dubeye1545422019-05-22 12:53:45 +0000493 public void checkForPacketFromUnknownServer(String hostAddress) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700494 if (!hostAddress.equals(configuredAaaServerAddress)) {
495 getConfiguredAaaServerAddress();
kartikey dubeye1545422019-05-22 12:53:45 +0000496 if (!hostAddress.equals(configuredAaaServerAddress)) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700497 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
kartikey dubeye1545422019-05-22 12:53:45 +0000498 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700499 }
kartikey dubeye1545422019-05-22 12:53:45 +0000500 }
501
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100502 /**
503 * Send RADIUS packet to the RADIUS server.
504 *
505 * @param radiusPacket RADIUS packet to be sent to server.
506 * @param inPkt Incoming EAPOL packet
507 */
508 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000509 outPacketSet.add(radiusPacket.getIdentifier());
510 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
511 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000512 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100513 impl.sendRadiusPacket(radiusPacket, inPkt);
514 }
Ray Milkey967776a2015-10-07 14:37:17 -0700515
Jonathan Hart612651f2019-11-25 09:21:43 -0800516 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100517 * Handles RADIUS packets.
518 *
519 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100520 */
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700521 public void handleRadiusPacket(RADIUS radiusPacket) {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200522 if (log.isTraceEnabled()) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700523 log.trace("Received RADIUS packet {} with identifier {}",
524 radiusPacket, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200525 }
526 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700527 if (log.isTraceEnabled()) {
528 log.trace("Handling operational status RADIUS packet {} with identifier {}",
529 radiusPacket, radiusPacket.getIdentifier() & 0xff);
530 }
Andrea Campanellac4781e62020-10-08 12:58:45 +0200531 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
532 return;
533 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800534
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700535 if (log.isTraceEnabled()) {
536 log.trace("Handling actual RADIUS packet for supplicant {} with identifier {}",
537 radiusPacket, radiusPacket.getIdentifier() & 0xff);
538 }
539
Andrea Campanellac4781e62020-10-08 12:58:45 +0200540 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
541 String sessionId = idManager.getSessionId(identifier);
Jonathan Hart612651f2019-11-25 09:21:43 -0800542
Andrea Campanellac4781e62020-10-08 12:58:45 +0200543 if (sessionId == null) {
544 log.error("Invalid packet identifier {}, could not find corresponding "
545 + "state machine ... exiting", radiusPacket.getIdentifier());
546 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
547 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
548 return;
549 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800550
Andrea Campanellac4781e62020-10-08 12:58:45 +0200551 idManager.releaseIdentifier(identifier);
552 StateMachine stateMachine = stateMachines.get(sessionId);
553 if (stateMachine == null) {
554 log.error("Invalid packet identifier {}, could not find corresponding "
555 + "state machine ... exiting", radiusPacket.getIdentifier());
556 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
557 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
558 return;
559 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000560
Andrea Campanellac4781e62020-10-08 12:58:45 +0200561 //instance of StateMachine using the sessionId for updating machine stats
562 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000563
Andrea Campanellac4781e62020-10-08 12:58:45 +0200564 EAP eapPayload;
565 Ethernet eth;
566 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000567
Andrea Campanellac4781e62020-10-08 12:58:45 +0200568 //increasing packets and octets received from server
569 machineStats.incrementTotalPacketsReceived();
570 try {
571 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
572 } catch (DeserializationException e) {
573 log.error(e.getMessage());
574 return;
575 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700576
Andrea Campanellac4781e62020-10-08 12:58:45 +0200577 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
578 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
579 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
580 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700581
Andrea Campanellac4781e62020-10-08 12:58:45 +0200582 MacAddress dstMac = stateMachine.supplicantAddress();
583 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
584 switch (radiusPacket.getCode()) {
585 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700586 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE for dev/port: {}/{} " +
587 "with MacAddress {} and Identifier {}",
588 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200589 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
590 byte[] challengeState = null;
591 if (radiusAttrState != null) {
592 challengeState = radiusAttrState.getValue();
593 }
594 try {
595 eapPayload = radiusPacket.decapsulateMessage();
596 eth = buildEapolResponse(stateMachine.supplicantAddress(),
597 MacAddress.valueOf(nasMacAddress),
598 stateMachine.vlanId(),
599 EAPOL.EAPOL_PACKET,
600 eapPayload, stateMachine.priorityCode());
601 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
602 } catch (DeserializationException e) {
603 log.error(e.getMessage());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700604 break;
Andrea Campanellac4781e62020-10-08 12:58:45 +0200605 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700606 log.debug("Send EAP challenge response to supplicant on dev/port: {}/{}" +
607 " with MacAddress {} and Identifier {}",
608 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200609 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
610 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
611 outPacketSupp.add(eapPayload.getIdentifier());
Andrea Campanella76ae68d2020-10-14 11:16:37 +0200612 aaaStatisticsManager.getAaaStats().incrementPendingReqSupp();
Andrea Campanellac4781e62020-10-08 12:58:45 +0200613 //increasing packets send to server
614 machineStats.incrementTotalPacketsSent();
615 machineStats.incrementTotalOctetSent(eapPayload.getLength());
616 break;
617 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700618 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT for dev/port: {}/{}" +
619 " with MacAddress {} and Identifier {}",
620 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200621 //send an EAPOL - Success to the supplicant.
622 byte[] eapMessageSuccess =
623 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
624 try {
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700625 eapPayload = EAP.deserializer().deserialize(
626 eapMessageSuccess, 0, eapMessageSuccess.length);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200627 } catch (DeserializationException e) {
628 log.error(e.getMessage());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700629 break;
Andrea Campanellac4781e62020-10-08 12:58:45 +0200630 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700631
Andrea Campanellac4781e62020-10-08 12:58:45 +0200632 eth = buildEapolResponse(stateMachine.supplicantAddress(),
633 MacAddress.valueOf(nasMacAddress),
634 stateMachine.vlanId(),
635 EAPOL.EAPOL_PACKET,
636 eapPayload, stateMachine.priorityCode());
Matteo Scandoloe033c262020-10-14 11:37:39 -0700637 log.info("Send EAP success message to supplicant on dev/port: {}/{}" +
638 " with MacAddress {} and Identifier {}",
639 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200640 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
641 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
642
643 stateMachine.authorizeAccess();
644 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
645 //increasing packets send to server
646 machineStats.incrementTotalPacketsSent();
647 machineStats.incrementTotalOctetSent(eapPayload.getLength());
648 break;
649 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700650 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT for dev/port: {}/{}" +
651 " with MacAddress {} and Identifier {}",
652 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200653 //send an EAPOL - Failure to the supplicant.
654 byte[] eapMessageFailure;
655 eapPayload = new EAP();
656 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
657 if (radiusAttrEap == null) {
658 eapPayload.setCode(EAP.FAILURE);
659 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
660 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
661 } else {
662 eapMessageFailure = radiusAttrEap.getValue();
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700663 try {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200664 eapPayload = EAP.deserializer().deserialize(
665 eapMessageFailure, 0, eapMessageFailure.length);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700666 } catch (DeserializationException e) {
667 log.error(e.getMessage());
668 break;
669 }
Andrea Campanellac4781e62020-10-08 12:58:45 +0200670 }
671 eth = buildEapolResponse(stateMachine.supplicantAddress(),
672 MacAddress.valueOf(nasMacAddress),
673 stateMachine.vlanId(),
674 EAPOL.EAPOL_PACKET,
675 eapPayload, stateMachine.priorityCode());
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700676 log.warn("Send EAP failure message to supplicant on dev/port: {}/{}" +
Matteo Scandoloe033c262020-10-14 11:37:39 -0700677 " with MacAddress {} and Identifier {}", supplicantCp.deviceId(), supplicantCp.port(),
678 dstMac, stateMachine.challengeIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200679 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
680 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
681
682 stateMachine.denyAccess();
683 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
684 //increasing packets send to server
685 machineStats.incrementTotalPacketsSent();
686 machineStats.incrementTotalOctetSent(eapPayload.getLength());
687 //pushing machine stats to kafka
688 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
689 aaaSupplicantStatsManager.getMachineStatsDelegate()
690 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE,
691 machineObj));
692 break;
693 default:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700694 log.warn("Unknown RADIUS message received with code: {} for dev/port: {}/{}" +
695 " with MacAddress {} and Identifier {}",
696 radiusPacket.getCode(), supplicantCp.deviceId(), supplicantCp.port(), dstMac,
697 radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200698 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
699 //increasing packets received to server
700 machineStats.incrementTotalPacketsReceived();
701 try {
702 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
703 } catch (DeserializationException e) {
704 log.error(e.getMessage());
705 break;
706 }
707 }
708 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700709 }
710
Ray Milkey967776a2015-10-07 14:37:17 -0700711 /**
712 * Send the ethernet packet to the supplicant.
713 *
714 * @param ethernetPkt the ethernet packet
715 * @param connectPoint the connect point to send out
716 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000717 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700718 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
719 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
720 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000721 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700722 if (log.isTraceEnabled()) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700723 log.trace("Sending eapol payload {} to supplicant at {} with MacAddress {}",
724 eap, connectPoint, ethernetPkt.getDestinationMAC());
Saurav Das987441a2018-09-18 16:33:47 -0700725 }
Ray Milkey967776a2015-10-07 14:37:17 -0700726 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000727 if (isChallengeResponse) {
728 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
729 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000730 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
731 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700732 }
733
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400734 @Override
735 public String toString() {
736 return ToStringBuilder.reflectionToString(this);
737 }
738
Jonathan Hart612651f2019-11-25 09:21:43 -0800739 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800740 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
Hardik Windlassd0b49692020-02-26 18:17:14 +0000741 return authentications.values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800742 }
743
744 @Override
745 public boolean removeAuthenticationStateByMac(MacAddress mac) {
746
Hardik Windlassd0b49692020-02-26 18:17:14 +0000747 Optional<AuthenticationRecord> r = authentications.values().stream()
748 .filter(v -> v.supplicantAddress().equals(mac))
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800749 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800750
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800751 if (r.isEmpty()) {
752 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800753 }
754
Hardik Windlassd0b49692020-02-26 18:17:14 +0000755 AuthenticationRecord removed =
756 authentications.remove(r.get().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800757
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800758 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800759 }
760
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800761 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800762 return stateMachines.get(sessionId);
763 }
764
765 private String sessionId(ConnectPoint cp) {
766 return cp.deviceId().toString() + cp.port().toString();
767 }
768
Ari Saha89831742015-06-26 10:31:48 -0700769 // our handler defined as a private inner class
770
771 /**
772 * Packet processor responsible for forwarding packets along their paths.
773 */
774 private class ReactivePacketProcessor implements PacketProcessor {
775 @Override
776 public void process(PacketContext context) {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200777 packetProcessorExecutor.execute(() -> {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700778 try {
779 // Extract the original Ethernet frame from the packet information
780 InboundPacket pkt = context.inPacket();
781 if (pkt == null) {
782 log.warn("Dropping inbound packet as it can't be parsed (inpacket)");
783 return;
784 }
785 Ethernet ethPkt = pkt.parsed();
786 if (ethPkt == null) {
787 log.warn("Dropping inbound packet as it can't be parsed (ethpacket)");
788 return;
789 }
Ari Saha89831742015-06-26 10:31:48 -0700790
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700791 EthType.EtherType pktType;
792 try {
793 short ethType = ethPkt.getEtherType();
794 pktType = EthType.EtherType.lookup(ethType);
795 } catch (Exception e) {
796 log.error("Exception while reading packet type", e);
797 return;
798 }
799
800 // identify if incoming packet comes from supplicant (EAP) or RADIUS
801 switch (pktType) {
802 case EAPOL:
803 if (log.isTraceEnabled()) {
804 log.trace("Received EAPOL supplicant packet from dev/port: {} with MacAddress {}",
805 context.inPacket().receivedFrom(), ethPkt.getSourceMAC());
806 }
807 handleSupplicantPacket(context.inPacket());
808 break;
809 default:
810 // any other packets let the specific implementation handle
811 if (log.isTraceEnabled()) {
812 log.trace("Received packet-in from RADIUS server {} in enclosing packet {} from "
813 + "dev/port: {} with MacAddress {}", ethPkt, context.inPacket(),
814 context.inPacket().receivedFrom(), ethPkt.getSourceMAC());
815 }
816 impl.handlePacketFromServer(context);
817 }
818 } catch (Exception e) {
819 log.error("Error while processing packet", e);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200820 }
821 });
Ari Saha89831742015-06-26 10:31:48 -0700822 }
823
Ray Milkey9eb293f2015-09-30 15:09:17 -0700824 /**
825 * Creates and initializes common fields of a RADIUS packet.
826 *
Ray Milkey967776a2015-10-07 14:37:17 -0700827 * @param stateMachine state machine for the request
Matteo Scandoloe033c262020-10-14 11:37:39 -0700828 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700829 * @return RADIUS packet
830 */
Ray Milkey967776a2015-10-07 14:37:17 -0700831 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700832 RADIUS radiusPayload =
833 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
834 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700835
836 // set Request Authenticator in StateMachine
837 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
838
Ray Milkey9eb293f2015-09-30 15:09:17 -0700839 radiusPayload.setIdentifier(identifier);
840 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700841 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700842
843 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700844 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700845
846 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700847
848 return radiusPayload;
849 }
Ari Saha89831742015-06-26 10:31:48 -0700850
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700851 private void handleEapolStart(InboundPacket inPacket, StateMachine stateMachine) {
852
853 DeviceId deviceId = inPacket.receivedFrom().deviceId();
854 PortNumber portNumber = inPacket.receivedFrom().port();
855 Ethernet ethPkt = inPacket.parsed();
856 MacAddress srcMac = ethPkt.getSourceMAC();
857
858 log.debug("EAP packet: EAPOL_START from dev/port: {}/{} with MacAddress {}",
859 deviceId, portNumber, srcMac);
860 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
861 stateMachine.setSupplicantAddress(srcMac);
862 stateMachine.start();
863
864 aaaStatisticsManager.getAaaStats().incrementEapolStartReqRx();
865 //send an EAP Request/Identify to the supplicant
866 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
867 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
868 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
869 }
870 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
871 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
872 eapPayload, stateMachine.priorityCode());
873
874 stateMachine.setVlanId(ethPkt.getVlanID());
875 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
876 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
877 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
878 }
879
880 private void hangleEapolLogoff(InboundPacket inPacket, StateMachine stateMachine) {
881
882 DeviceId deviceId = inPacket.receivedFrom().deviceId();
883 PortNumber portNumber = inPacket.receivedFrom().port();
884 Ethernet ethPkt = inPacket.parsed();
885 MacAddress srcMac = ethPkt.getSourceMAC();
886
887 log.debug("EAP packet: EAPOL_LOGOFF from dev/port: {}/{} with MacAddress {}",
888 deviceId, portNumber, srcMac);
889 //posting the machine stat data for current supplicant device.
890 if (stateMachine.getSessionTerminateReason() == null ||
891 stateMachine.getSessionTerminateReason().equals("")) {
892 stateMachine.setSessionTerminateReason(
893 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
894 }
895 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
896 aaaSupplicantStatsManager.getMachineStatsDelegate()
897 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
898 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
899 stateMachine.logoff();
900 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
901 }
902 if (stateMachine.state() == StateMachine.STATE_IDLE) {
903 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
904 }
905 }
906
907 private void handleForgedEapolChallengeAuth(StateMachine stateMachine) {
908 stateMachine.requestAccess();
909
910 log.info("Forging EAP auth challenge");
911 byte[] challengeState = EapolPacketGenerator.hexStringToByteArray("19056d66190469d738db2f7dc1e02591");
912 EAP eapPayload = EapolPacketGenerator.forgeEapolChallengeAuth();
913
914 Ethernet eth = buildEapolResponse(stateMachine.supplicantAddress(),
915 MacAddress.valueOf(nasMacAddress),
916 stateMachine.vlanId(),
917 EAPOL.EAPOL_PACKET,
918 eapPayload, stateMachine.priorityCode());
919 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
920
921 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
922 MacAddress dstMac = stateMachine.supplicantAddress();
923 log.info("Send FORGED EAP auth challenge to supplicant {} on dev/port: {}/{} with MacAddress {}",
924 supplicantCp.deviceId(), supplicantCp.port(), dstMac);
925
926 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(),
927 true);
928
929 // NOTE do we care about stats?
930 }
931
932 private void handleForgedEapolSuccess(StateMachine stateMachine) {
933 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
934 MacAddress dstMac = stateMachine.supplicantAddress();
935 log.info("Forging EAP auth success");
936 EAP eapPayload = EapolPacketGenerator.forgeEapolSuccess();
937
938 Ethernet eth = buildEapolResponse(stateMachine.supplicantAddress(),
939 MacAddress.valueOf(nasMacAddress),
940 stateMachine.vlanId(),
941 EAPOL.EAPOL_PACKET,
942 eapPayload, stateMachine.priorityCode());
943 log.info("Send FORGED EAP success message to supplicant {} on dev/port: {}/{} with MacAddress {}",
944 supplicantCp.deviceId(), supplicantCp.port(), dstMac);
945 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
946 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
947
948 stateMachine.authorizeAccess();
949 }
950
951
Ari Saha89831742015-06-26 10:31:48 -0700952 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700953 * Handles PAE packets (supplicant).
954 *
955 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700956 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800957 private void handleSupplicantPacket(InboundPacket inPacket) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700958
Jonathan Harta46dddf2015-06-30 15:31:20 -0700959 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700960 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800961 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700962
Jonathan Harta46dddf2015-06-30 15:31:20 -0700963 DeviceId deviceId = inPacket.receivedFrom().deviceId();
964 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800965 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700966 EAPOL eapol = (EAPOL) ethPkt.getPayload();
Matteo Scandoloe033c262020-10-14 11:37:39 -0700967
Saurav Das987441a2018-09-18 16:33:47 -0700968 if (log.isTraceEnabled()) {
969 log.trace("Received EAPOL packet {} in enclosing packet {} from "
Matteo Scandoloe033c262020-10-14 11:37:39 -0700970 + "dev/port: {}/{} with MacAddress {} and type {}",
971 eapol, ethPkt, deviceId, portNumber, srcMac, eapol.getEapolType());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100972 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700973
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000974 short pktlen = eapol.getPacketLength();
975 byte[] eapPayLoadBuffer = eapol.serialize();
976 int len = eapPayLoadBuffer.length;
977 if (len != (HEADER_LENGTH + pktlen)) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700978 log.warn("Invalid EAPOL pkt length {} (shoudl be {}) for packet {} from dev/port: {}/{} " +
979 "with MacAddress {}, dropping it",
980 len, HEADER_LENGTH + pktlen, eapol, deviceId, portNumber, srcMac);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000981 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
982 return;
983 }
984 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700985 log.warn("Invalid EAPOL Type {} for packet {} from dev/port: {}/{} with MacAddress {}, dropping it",
Matteo Scandoloe033c262020-10-14 11:37:39 -0700986 eapol.getEapolType(), eapol, deviceId, portNumber, srcMac);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000987 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
988 return;
989 }
990 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
991 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
992 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700993 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id ->
994 new StateMachine(id, serverStatusAndStateMachineTimeoutExecutor));
Jonathan Hart612651f2019-11-25 09:21:43 -0800995 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700996
Ari Saha89831742015-06-26 10:31:48 -0700997 switch (eapol.getEapolType()) {
998 case EAPOL.EAPOL_START:
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700999 handleEapolStart(inPacket, stateMachine);
Ari Saha89831742015-06-26 10:31:48 -07001000 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +08001001 case EAPOL.EAPOL_LOGOFF:
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001002 hangleEapolLogoff(inPacket, stateMachine);
Qianqian Hub55a1ac2015-12-23 20:44:48 +08001003 break;
Ari Saha89831742015-06-26 10:31:48 -07001004 case EAPOL.EAPOL_PACKET:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001005
Ray Milkey9eb293f2015-09-30 15:09:17 -07001006 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -07001007 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +00001008 Byte identifier = new Byte(eapPacket.getIdentifier());
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001009
Matteo Scandoloe033c262020-10-14 11:37:39 -07001010 log.debug("EAP packet: EAPOL_PACKET from dev/port: {}/{} with MacAddress {} with Identifier {}",
1011 deviceId, portNumber, srcMac, identifier.doubleValue());
Jonathan Hart612651f2019-11-25 09:21:43 -08001012
Ari Saha89831742015-06-26 10:31:48 -07001013 byte dataType = eapPacket.getDataType();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001014
Ari Saha89831742015-06-26 10:31:48 -07001015 switch (dataType) {
Ray Milkey9eb293f2015-09-30 15:09:17 -07001016 case EAP.ATTR_IDENTITY:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001017 handleAttrIdentity(inPacket, srcMac, deviceId, portNumber,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001018 eapol, stateMachine, eapPacket, sessionId);
Ray Milkey9eb293f2015-09-30 15:09:17 -07001019 break;
Ari Saha89831742015-06-26 10:31:48 -07001020 case EAP.ATTR_MD5:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001021 handleMD5(inPacket, srcMac, deviceId, portNumber, stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001022 eapPacket, identifier, sessionId);
Ari Saha89831742015-06-26 10:31:48 -07001023 break;
1024 case EAP.ATTR_TLS:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001025 handleTls(inPacket, srcMac, deviceId, portNumber, stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001026 eapPacket, identifier, sessionId);
Ari Saha89831742015-06-26 10:31:48 -07001027 break;
1028 default:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001029 log.warn("Unknown EAP packet type from dev/port: {}/{} with MacAddress {} and " +
1030 "Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
Ari Saha89831742015-06-26 10:31:48 -07001031 return;
1032 }
1033 break;
1034 default:
Andrea Campanellac4781e62020-10-08 12:58:45 +02001035 log.debug("Skipping EAPOL message {} from dev/port: {}/{} with MacAddress {}",
1036 eapol.getEapolType(), deviceId, portNumber, srcMac);
Ari Saha89831742015-06-26 10:31:48 -07001037 }
Shubham Sharma1f193582019-07-11 12:12:41 +00001038 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
1039 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -07001040 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001041
1042 private void handleAttrIdentity(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1043 PortNumber portNumber, EAPOL eapol, StateMachine stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001044 EAP eapPacket, String sessionId) {
Matteo Scandoloe033c262020-10-14 11:37:39 -07001045
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001046 if (forgeEapolPackets) {
1047 handleForgedEapolChallengeAuth(stateMachine);
1048 return;
1049 } else {
1050 // get identifier for request and store mapping to session ID
1051 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1052 if (radiusIdentifier == null) {
1053 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1054 "with MacAddress {}, dropping packet",
1055 deviceId, portNumber, srcMac);
1056 return;
1057 }
1058 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY from dev/port: {}/{} with MacAddress {}" +
1059 " and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1060 //Setting the time of this response from RG, only when its not a re-transmission.
1061 if (stateMachine.getLastPacketReceivedTime() == 0) {
1062 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
1063 }
1064 // request id access to RADIUS
1065 stateMachine.setUsername(eapPacket.getData());
Matteo Scandoloe033c262020-10-14 11:37:39 -07001066
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001067 RADIUS radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
1068 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
1069 radiusPayload.addMessageAuthenticator(radiusSecret);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001070
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001071 if (log.isTraceEnabled()) {
1072 log.trace("Sending ATTR_IDENTITY packet to RADIUS for supplicant at dev/port: " +
1073 "{}/{} with MacAddress {} and Identifier {}", deviceId, portNumber,
1074 srcMac, radiusIdentifier.identifier() & 0xff);
1075 }
1076
1077 sendRadiusPacket(radiusPayload, inPacket);
1078 stateMachine.setWaitingForRadiusResponse(true);
1079 aaaStatisticsManager.getAaaStats().incrementRadiusReqIdTx();
1080 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
1081 // change the state to "PENDING"
1082 if (stateMachine.state() == StateMachine.STATE_PENDING) {
1083 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
1084 stateMachine.incrementTotalPacketsSent();
1085 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
1086 }
1087 stateMachine.requestAccess();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001088 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001089 }
1090
1091 private void handleMD5(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1092 PortNumber portNumber, StateMachine stateMachine, EAP eapPacket,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001093 Byte identifier, String sessionId) {
1094 // get identifier for request and store mapping to session ID
1095 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1096 if (radiusIdentifier == null) {
1097 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1098 "with MacAddress {}, dropping packet",
1099 deviceId, portNumber, srcMac);
1100 return;
1101 }
1102
Matteo Scandoloe033c262020-10-14 11:37:39 -07001103 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5 from dev/port: {}/{} with MacAddress {}" +
1104 " and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1105 // verify if the EAP identifier corresponds to the
1106 // challenge identifier from the client state
1107 // machine.
1108 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
1109 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
1110 //send the RADIUS challenge response
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001111 if (forgeEapolPackets) {
1112 handleForgedEapolSuccess(stateMachine);
1113 } else {
1114 RADIUS radiusPayload = getRadiusPayload(stateMachine,
1115 radiusIdentifier.identifier(), eapPacket);
1116 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001117
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001118 if (stateMachine.challengeState() != null) {
1119 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
1120 stateMachine.challengeState());
1121 }
1122 radiusPayload.addMessageAuthenticator(radiusSecret);
1123 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1124 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1125 outPacketSupp.remove(identifier);
1126 }
1127 if (log.isTraceEnabled()) {
1128 log.trace("Sending ATTR_MD5 packet to RADIUS for supplicant at dev/port: {}/{}" +
1129 " with MacAddress {} and Identifier {}", deviceId, portNumber, srcMac,
1130 radiusIdentifier.identifier() & 0xff);
1131 }
1132 sendRadiusPacket(radiusPayload, inPacket);
1133 stateMachine.setWaitingForRadiusResponse(true);
1134 aaaStatisticsManager.getAaaStats().incrementRadiusReqChallengeTx();
1135 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001136 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001137 } else {
1138 log.error("eapolIdentifier {} and stateMachine Identifier {} do not " +
1139 "correspond for packet from dev/port: {}/{} with MacAddress {}",
1140 eapPacket.getIdentifier() & 0xff, stateMachine.challengeIdentifier() & 0xff,
1141 deviceId, portNumber, srcMac);
1142 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
1143 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1144 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1145 outPacketSupp.remove(identifier);
1146 }
1147 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
1148 }
1149 }
1150
1151
1152 private void handleTls(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1153 PortNumber portNumber, StateMachine stateMachine, EAP eapPacket,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001154 Byte identifier, String sessionId) {
1155 // get identifier for request and store mapping to session ID
1156 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1157
1158 if (radiusIdentifier == null) {
1159 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1160 "with MacAddress {}, dropping packet", deviceId, portNumber, srcMac);
1161 return;
1162 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001163 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS from dev/port: {}/{} with MacAddress {} " +
1164 "and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1165 // request id access to RADIUS
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001166 RADIUS radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001167 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
1168 if (stateMachine.challengeState() != null) {
1169 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
1170 stateMachine.challengeState());
1171 }
1172 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
1173 radiusPayload.addMessageAuthenticator(radiusSecret);
1174 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1175 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1176 outPacketSupp.remove(identifier);
1177 }
1178 if (log.isTraceEnabled()) {
1179 log.trace("Sending ATTR_TLS packet to RADIUS for supplicant at dev/port: {}/{} with " +
1180 "MacAddress {} and Identifier {}", deviceId, portNumber, srcMac,
1181 radiusIdentifier.identifier() & 0xff);
1182 }
1183 sendRadiusPacket(radiusPayload, inPacket);
1184 stateMachine.setWaitingForRadiusResponse(true);
1185 aaaStatisticsManager.getAaaStats().incrementRadiusReqChallengeTx();
1186 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
1187 if (stateMachine.state() != StateMachine.STATE_PENDING) {
1188 stateMachine.requestAccess();
1189 }
1190 }
Ray Milkey967776a2015-10-07 14:37:17 -07001191 }
1192
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001193 /**
Jonathan Hart5db44532018-07-12 18:13:54 -07001194 * Delegate allowing the StateMachine to notify us of events.
1195 */
1196 private class InternalStateMachineDelegate implements StateMachineDelegate {
1197
1198 @Override
1199 public void notify(AuthenticationEvent authenticationEvent) {
1200 log.info("Auth event {} for {}",
Matteo Scandoloe033c262020-10-14 11:37:39 -07001201 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -08001202
1203 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
1204 handleStateMachineTimeout(authenticationEvent.subject());
1205 }
1206
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001207 AuthenticationRecord record = authenticationEvent.authenticationRecord();
1208 if (record == null) {
1209 authentications.remove(authenticationEvent.subject());
1210 } else {
1211 authentications.put(authenticationEvent.subject(), record);
1212 }
1213
Jonathan Hart5db44532018-07-12 18:13:54 -07001214 post(authenticationEvent);
1215 }
1216 }
1217
Jonathan Hart612651f2019-11-25 09:21:43 -08001218 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
1219 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
Andrea Campanellae66466a2020-02-03 14:05:45 +00001220 //pushing captured machine stats to kafka
1221 stateMachine.setSessionTerminateReason("Time out");
1222 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
1223 .getSupplicantStats(stateMachine);
1224 aaaSupplicantStatsManager.getMachineStatsDelegate()
1225 .notify(new AaaMachineStatisticsEvent(
1226 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
1227
Jonathan Hart612651f2019-11-25 09:21:43 -08001228 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
1229 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
1230 }
1231
1232 StateMachine.deleteStateMachineMapping(stateMachine);
1233 }
1234
Jonathan Hart5db44532018-07-12 18:13:54 -07001235 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001236 * Configuration Listener, handles change in configuration.
1237 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001238 private class InternalConfigListener implements NetworkConfigListener {
1239
1240 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -08001241 * Reconfigures the AAA application according to the
1242 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001243 *
1244 * @param cfg configuration object
1245 */
Jonathan Hart092dfb22015-11-16 23:05:21 -08001246 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001247 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001248
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001249 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -08001250 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001251 } else {
1252 newCfg = cfg;
1253 }
1254 if (newCfg.nasIp() != null) {
1255 nasIpAddress = newCfg.nasIp();
1256 }
1257 if (newCfg.radiusIp() != null) {
1258 radiusIpAddress = newCfg.radiusIp();
1259 }
1260 if (newCfg.radiusMac() != null) {
1261 radiusMacAddress = newCfg.radiusMac();
1262 }
1263 if (newCfg.nasMac() != null) {
1264 nasMacAddress = newCfg.nasMac();
1265 }
Andrea Campanellac4781e62020-10-08 12:58:45 +02001266 if (newCfg.radiusSecret() != null && !newCfg.radiusSecret().equals(radiusSecret)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001267 radiusSecret = newCfg.radiusSecret();
Andrea Campanellac4781e62020-10-08 12:58:45 +02001268 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001269 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001270
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301271 boolean reconfigureCustomizer = false;
1272 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
1273 customizer = newCfg.radiusPktCustomizer();
1274 configurePacketCustomizer();
1275 reconfigureCustomizer = true;
1276 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001277
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301278 if (radiusConnectionType == null
1279 || reconfigureCustomizer
1280 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
1281 radiusConnectionType = newCfg.radiusConnectionType();
1282 if (impl != null) {
1283 impl.withdrawIntercepts();
1284 impl.clearLocalState();
1285 }
1286 configureRadiusCommunication();
1287 impl.initializeLocalState(newCfg);
1288 impl.requestIntercepts();
1289 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001290 impl.clearLocalState();
1291 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -07001292 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001293 }
1294
1295 @Override
1296 public void event(NetworkConfigEvent event) {
1297
1298 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1299 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001300 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001301
Jonathan Hart092dfb22015-11-16 23:05:21 -08001302 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001303 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001304
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001305 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001306 }
1307 }
1308 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001309
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001310 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1311 @Override
1312 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1313 if (event.type() == MapEvent.Type.REMOVE) {
1314 // remove local state machine if user has requested remove
1315 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1316 if (sm != null) {
1317 sm.stop();
1318 }
1319 }
1320 }
1321 }
1322
Amit Ghoshf739be52017-09-21 15:49:37 +01001323 private class InternalDeviceListener implements DeviceListener {
1324 @Override
1325 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001326 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001327 switch (event.type()) {
1328 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001329 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001330 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001331 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
Hardik Windlass75c67712020-02-21 10:57:20 +00001332
Girish Kumar064084c2020-02-04 08:32:46 +00001333 flushStateMachineSession(sessionId,
Matteo Scandoloe033c262020-10-14 11:37:39 -07001334 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001335
Girish Kumar064084c2020-02-04 08:32:46 +00001336 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001337 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001338 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001339 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001340 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001341
Amit Ghoshf739be52017-09-21 15:49:37 +01001342 default:
1343 return;
1344 }
1345 }
Girish Kumar064084c2020-02-04 08:32:46 +00001346
Andrea Campanellabba33672020-02-11 14:03:01 +01001347 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1348 Set<String> associatedSessions = Sets.newHashSet();
1349 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1350 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1351 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1352 associatedSessions.add(stateMachineEntry.getKey());
1353 }
1354 }
1355
1356 for (String session : associatedSessions) {
1357 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1358 flushStateMachineSession(session,
Matteo Scandoloe033c262020-10-14 11:37:39 -07001359 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
Andrea Campanellabba33672020-02-11 14:03:01 +01001360 }
1361 }
1362
Girish Kumar064084c2020-02-04 08:32:46 +00001363 private void flushStateMachineSession(String sessionId, String terminationReason) {
1364 StateMachine stateMachine = stateMachines.get(sessionId);
Girish Kumare5a1aa92020-02-14 14:08:54 +00001365 if (stateMachine == null) {
1366 // No active AAA sessions for this UNI port
1367 log.debug("No Active AAA Session found with Id {}", sessionId);
1368 return;
Girish Kumar064084c2020-02-04 08:32:46 +00001369 }
1370
Hardik Windlass9a09b832020-02-25 11:45:35 +00001371 authentications.remove(stateMachine.supplicantConnectpoint());
Girish Kumare5a1aa92020-02-14 14:08:54 +00001372 stateMachine.setSessionTerminateReason(terminationReason);
1373
Girish Kumar064084c2020-02-04 08:32:46 +00001374 //pushing captured machine stats to kafka
1375 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1376 aaaSupplicantStatsManager.getMachineStatsDelegate()
Matteo Scandoloe033c262020-10-14 11:37:39 -07001377 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Girish Kumar064084c2020-02-04 08:32:46 +00001378 StateMachine removed = stateMachines.remove(sessionId);
Shubham Sharma8d7a9822020-01-28 10:04:01 +00001379
Girish Kumar064084c2020-02-04 08:32:46 +00001380 if (removed != null) {
1381 StateMachine.deleteStateMachineMapping(removed);
1382 }
1383 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001384 }
Girish Kumar064084c2020-02-04 08:32:46 +00001385
Shubham Sharma4900ce62019-06-19 14:18:50 +00001386 private class ServerStatusChecker implements Runnable {
1387 @Override
1388 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001389 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001390 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001391 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001392 radiusOperationalStatusService.getRadiusOprStDelegate()
Matteo Scandoloe033c262020-10-14 11:37:39 -07001393 .notify(new RadiusOperationalStatusEvent(
1394 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1395 radiusOperationalStatusService.
1396 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001397 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001398
1399 }
Shubham Sharma544ffa22020-02-13 06:41:02 +00001400
1401 @Override
1402 public AaaSupplicantMachineStats getSupplicantMachineStats(String sessionId) {
1403 StateMachine aaaSupplicantMachine = stateMachines.get(sessionId);
1404 if (aaaSupplicantMachine != null) {
1405 return aaaSupplicantStatsManager.getSupplicantStats(aaaSupplicantMachine);
1406 } else {
1407 return null;
1408 }
1409 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001410}