blob: d4f0fbbc6da75c84e3883b0eb503562fc4ab8979 [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;
191 private Map<ConnectPoint, AuthenticationRecord> authentications;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800192
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700193 // NAS IP address
194 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100195
196 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700197 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100198
199 // Parsed RADIUS server addresses
200 protected InetAddress radiusIpAddress;
201
202 // MAC address of RADIUS server or net hop router
203 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700204
205 // RADIUS server secret
206 protected String radiusSecret;
207
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100208 // bindings
209 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700210
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700211 // our application-specific event handler
212 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700213
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700214 // our unique identifier
215 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700216
Shubham Sharma1e43c562019-06-19 14:18:12 +0000217 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
218 protected int cleanupTimerTimeOutInMins;
219
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100220 // Setup specific customization/attributes on the RADIUS packets
221 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700222
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100223 // packet customizer to use
224 private String customizer;
225
226 // Type of connection to use to communicate with Radius server, options are
227 // "socket" or "packet_out"
228 private String radiusConnectionType;
229
Jonathan Hart5db44532018-07-12 18:13:54 -0700230 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100231 // server, socket based or packet_out based
232 RadiusCommunicator impl = null;
233
234 // latest configuration
235 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700236
Shubham Sharma4900ce62019-06-19 14:18:50 +0000237 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000238 String configuredAaaServerAddress;
Jonathan Hartc41227c2020-01-28 16:56:49 -0800239 HashSet<Byte> outPacketSet = new HashSet<>();
240 HashSet<Byte> outPacketSupp = new HashSet<>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000241 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
242 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700243 // Configuration properties factory
244 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800245 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700246 AaaConfig.class,
247 "AAA") {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700248 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800249 public AaaConfig createConfig() {
250 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700251 }
252 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700253
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700254 // Listener for config changes
255 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700256
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800257 private final InternalMapEventListener mapListener = new InternalMapEventListener();
258
Jonathan Hart5db44532018-07-12 18:13:54 -0700259 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
260
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700261 protected ExecutorService packetProcessorExecutor;
262 protected ScheduledExecutorService serverStatusAndStateMachineTimeoutExecutor;
Matteo Scandoloe033c262020-10-14 11:37:39 -0700263
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700264 /**
265 * Builds an EAPOL packet based on the given parameters.
266 *
267 * @param dstMac destination MAC address
268 * @param srcMac source MAC address
269 * @param vlan vlan identifier
270 * @param eapolType EAPOL type
271 * @param eap EAP payload
272 * @return Ethernet frame
273 */
274 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100275 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700276
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700277 Ethernet eth = new Ethernet();
278 eth.setDestinationMACAddress(dstMac.toBytes());
279 eth.setSourceMACAddress(srcMac.toBytes());
280 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
281 if (vlan != Ethernet.VLAN_UNTAGGED) {
282 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100283 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700284 }
285 //eapol header
286 EAPOL eapol = new EAPOL();
287 eapol.setEapolType(eapolType);
288 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700289
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700290 //eap part
291 eapol.setPayload(eap);
292
293 eth.setPayload(eapol);
294 eth.setPad(true);
295 return eth;
296 }
Ari Saha89831742015-06-26 10:31:48 -0700297
Ari Saha89831742015-06-26 10:31:48 -0700298 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000299 public void activate(ComponentContext context) {
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700300
Jonathan Hart612651f2019-11-25 09:21:43 -0800301 idManager = new IdentifierManager();
302 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800303 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800304
305 KryoNamespace authSerializer = KryoNamespace.newBuilder()
Jonathan Hartc41227c2020-01-28 16:56:49 -0800306 .register(KryoNamespaces.API)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800307 .register(AuthenticationRecord.class)
308 .build();
309
Hardik Windlassd0b49692020-02-26 18:17:14 +0000310 authenticationsConsistentMap = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800311 .withApplicationId(appId)
312 .withName("authentications")
313 .withSerializer(Serializer.using(authSerializer))
314 .build();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000315 authenticationsConsistentMap.addListener(mapListener);
316 authentications = authenticationsConsistentMap.asJavaMap();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800317
Jonathan Hart5db44532018-07-12 18:13:54 -0700318 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400319 netCfgService.addListener(cfgListener);
320 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000321 cfgService.registerProperties(getClass());
322 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000323 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530324 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800325 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400326 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530327 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700328 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700329 packetService.addProcessor(processor, PacketProcessor.director(2));
Jonathan Hart5db44532018-07-12 18:13:54 -0700330 StateMachine.setDelegate(delegate);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000331 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
332 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100333 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100334 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100335 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000336 getConfiguredAaaServerAddress();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000337 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700338 serverStatusAndStateMachineTimeoutExecutor = Executors.newScheduledThreadPool(STATE_MACHINE_THREADS,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700339 groupedThreads("onos/aaa", "machine-%d", log));
Shubham Sharma4900ce62019-06-19 14:18:50 +0000340
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700341 scheduledStatusServerChecker = serverStatusAndStateMachineTimeoutExecutor.scheduleAtFixedRate(
342 new ServerStatusChecker(), 0,
343 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100344
Jian Li13c67162015-12-09 13:20:34 -0800345 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700346 }
347
348 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000349 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100350 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700351 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530352 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000353 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700354 StateMachine.unsetDelegate(delegate);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100355 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100356 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700357 eventDispatcher.removeSink(AuthenticationEvent.class);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000358 scheduledStatusServerChecker.cancel(true);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700359 serverStatusAndStateMachineTimeoutExecutor.shutdown();
360 packetProcessorExecutor.shutdown();
Hardik Windlassd0b49692020-02-26 18:17:14 +0000361 authenticationsConsistentMap.removeListener(mapListener);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800362
Jian Li13c67162015-12-09 13:20:34 -0800363 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700364 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700365
kartikey dubeye1545422019-05-22 12:53:45 +0000366 @Modified
367 public void modified(ComponentContext context) {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000368 Dictionary<String, Object> properties = context.getProperties();
369
Jonathan Hartc41227c2020-01-28 16:56:49 -0800370 String s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
Shubham Sharma4900ce62019-06-19 14:18:50 +0000371 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
372 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
Matteo Scandoloe033c262020-10-14 11:37:39 -0700373 : Integer.parseInt(s.trim());
Shubham Sharma4900ce62019-06-19 14:18:50 +0000374
375 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
376 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
377 : Integer.parseInt(s.trim());
378
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700379 Boolean p = Tools.isPropertyEnabled(properties, FORGE_EAPOL_PACKETS);
380 forgeEapolPackets = (p == null) ? FORGE_EAPOL_PACKETS_DEFAULT : p;
381
Shubham Sharma4900ce62019-06-19 14:18:50 +0000382 s = Tools.get(properties, "operationalStatusEvaluationMode");
383 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
384
385 radiusOperationalStatusService
Matteo Scandoloe033c262020-10-14 11:37:39 -0700386 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000387 RadiusOperationalStatusEvaluationMode newEvaluationMode =
388 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
389 if (newEvaluationMode != null) {
390 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
391 operationalStatusEvaluationMode = newEvaluationModeString;
392 } else {
393 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
394 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700395
396 s = Tools.get(properties, PACKET_PROCESSOR_THREADS);
397 int oldpacketProcessorThreads = packetProcessorThreads;
398 packetProcessorThreads = Strings.isNullOrEmpty(s) ? oldpacketProcessorThreads
399 : Integer.parseInt(s.trim());
400 if (packetProcessorExecutor == null || oldpacketProcessorThreads != packetProcessorThreads) {
401 if (packetProcessorExecutor != null) {
402 packetProcessorExecutor.shutdown();
403 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700404 packetProcessorExecutor = newSingleThreadExecutor(
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700405 groupedThreads("onos/aaa", "packet-%d", log));
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700406 }
kartikey dubeye1545422019-05-22 12:53:45 +0000407 }
408
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000409 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530410 if (radiusConnectionType.toLowerCase().equals("socket")) {
411 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
412 } else {
413 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700414 deviceService, subsService, pktCustomizer, this);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530415 }
416 }
417
418 private void configurePacketCustomizer() {
419 switch (customizer.toLowerCase()) {
420 case "sample":
421 pktCustomizer = new SamplePacketCustomizer(customInfo);
422 log.info("Created SamplePacketCustomizer");
423 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800424 case "att":
425 pktCustomizer = new AttPacketCustomizer(customInfo);
426 log.info("Created AttPacketCustomizer");
427 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530428 default:
429 pktCustomizer = new PacketCustomizer(customInfo);
430 log.info("Created default PacketCustomizer");
431 break;
432 }
433 }
434
kartikey dubeye1545422019-05-22 12:53:45 +0000435 private void getConfiguredAaaServerAddress() {
436 try {
437 InetAddress address;
438 if (newCfg.radiusHostName() != null) {
439 address = InetAddress.getByName(newCfg.radiusHostName());
440 } else {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700441 address = newCfg.radiusIp();
kartikey dubeye1545422019-05-22 12:53:45 +0000442 }
443
444 configuredAaaServerAddress = address.getHostAddress();
445 } catch (UnknownHostException uhe) {
446 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
447 }
448 }
449
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000450 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
451 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000452 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
453 }
454 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000455
456 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
457 byte[] newHash = new byte[16];
458 Arrays.fill(newHash, (byte) 0);
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700459 // looking for the attributes - exit if there are no such attributes
460 if (radiusPacket.getAttributeList(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).isEmpty()) {
461 log.warn("Empty Attribute List for packet {} with identifier {}",
462 radiusPacket, radiusPacket.getIdentifier());
463 return false;
464 }
465 // get the attribute - further verify if it is null or not (not really needed)
466 RADIUSAttribute attribute = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH);
467 if (attribute == null) {
468 log.warn("Null Message Authenticator for packet {} with identifier {}",
469 radiusPacket, radiusPacket.getIdentifier());
470 return false;
471 }
472 byte[] messageAuthenticator = attribute.getValue();
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000473 byte[] authenticator = radiusPacket.getAuthenticator();
474 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
475 radiusPacket.setAuthenticator(requestAuthenticator);
476 // Calculate the MD5 HMAC based on the message
477 try {
478 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
479 Mac mac = Mac.getInstance("HmacMD5");
480 mac.init(keySpec);
481 newHash = mac.doFinal(radiusPacket.serialize());
482 } catch (Exception e) {
483 log.error("Failed to generate message authenticator: {}", e.getMessage());
484 }
485 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
486 radiusPacket.setAuthenticator(authenticator);
487 // Compare the calculated Message-Authenticator with the one in the message
488 return Arrays.equals(newHash, messageAuthenticator);
489 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700490
kartikey dubeye1545422019-05-22 12:53:45 +0000491 public void checkForPacketFromUnknownServer(String hostAddress) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700492 if (!hostAddress.equals(configuredAaaServerAddress)) {
493 getConfiguredAaaServerAddress();
kartikey dubeye1545422019-05-22 12:53:45 +0000494 if (!hostAddress.equals(configuredAaaServerAddress)) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700495 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
kartikey dubeye1545422019-05-22 12:53:45 +0000496 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700497 }
kartikey dubeye1545422019-05-22 12:53:45 +0000498 }
499
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100500 /**
501 * Send RADIUS packet to the RADIUS server.
502 *
503 * @param radiusPacket RADIUS packet to be sent to server.
504 * @param inPkt Incoming EAPOL packet
505 */
506 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000507 outPacketSet.add(radiusPacket.getIdentifier());
508 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
509 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000510 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100511 impl.sendRadiusPacket(radiusPacket, inPkt);
512 }
Ray Milkey967776a2015-10-07 14:37:17 -0700513
Jonathan Hart612651f2019-11-25 09:21:43 -0800514 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100515 * Handles RADIUS packets.
516 *
517 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100518 */
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700519 public void handleRadiusPacket(RADIUS radiusPacket) {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200520 if (log.isTraceEnabled()) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700521 log.trace("Received RADIUS packet {} with identifier {}",
522 radiusPacket, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200523 }
524 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700525 if (log.isTraceEnabled()) {
526 log.trace("Handling operational status RADIUS packet {} with identifier {}",
527 radiusPacket, radiusPacket.getIdentifier() & 0xff);
528 }
Andrea Campanellac4781e62020-10-08 12:58:45 +0200529 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
530 return;
531 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800532
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700533 if (log.isTraceEnabled()) {
534 log.trace("Handling actual RADIUS packet for supplicant {} with identifier {}",
535 radiusPacket, radiusPacket.getIdentifier() & 0xff);
536 }
537
Andrea Campanellac4781e62020-10-08 12:58:45 +0200538 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
539 String sessionId = idManager.getSessionId(identifier);
Jonathan Hart612651f2019-11-25 09:21:43 -0800540
Andrea Campanellac4781e62020-10-08 12:58:45 +0200541 if (sessionId == null) {
542 log.error("Invalid packet identifier {}, could not find corresponding "
543 + "state machine ... exiting", radiusPacket.getIdentifier());
544 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
545 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
546 return;
547 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800548
Andrea Campanellac4781e62020-10-08 12:58:45 +0200549 idManager.releaseIdentifier(identifier);
550 StateMachine stateMachine = stateMachines.get(sessionId);
551 if (stateMachine == null) {
552 log.error("Invalid packet identifier {}, could not find corresponding "
553 + "state machine ... exiting", radiusPacket.getIdentifier());
554 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
555 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
556 return;
557 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000558
Andrea Campanellac4781e62020-10-08 12:58:45 +0200559 //instance of StateMachine using the sessionId for updating machine stats
560 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000561
Andrea Campanellac4781e62020-10-08 12:58:45 +0200562 EAP eapPayload;
563 Ethernet eth;
564 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000565
Andrea Campanellac4781e62020-10-08 12:58:45 +0200566 //increasing packets and octets received from server
567 machineStats.incrementTotalPacketsReceived();
568 try {
569 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
570 } catch (DeserializationException e) {
571 log.error(e.getMessage());
572 return;
573 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700574
Andrea Campanellac4781e62020-10-08 12:58:45 +0200575 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
576 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
577 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
578 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700579
Andrea Campanellac4781e62020-10-08 12:58:45 +0200580 MacAddress dstMac = stateMachine.supplicantAddress();
581 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
582 switch (radiusPacket.getCode()) {
583 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700584 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE for dev/port: {}/{} " +
585 "with MacAddress {} and Identifier {}",
586 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200587 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
588 byte[] challengeState = null;
589 if (radiusAttrState != null) {
590 challengeState = radiusAttrState.getValue();
591 }
592 try {
593 eapPayload = radiusPacket.decapsulateMessage();
594 eth = buildEapolResponse(stateMachine.supplicantAddress(),
595 MacAddress.valueOf(nasMacAddress),
596 stateMachine.vlanId(),
597 EAPOL.EAPOL_PACKET,
598 eapPayload, stateMachine.priorityCode());
599 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
600 } catch (DeserializationException e) {
601 log.error(e.getMessage());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700602 break;
Andrea Campanellac4781e62020-10-08 12:58:45 +0200603 }
Matteo Scandoloe033c262020-10-14 11:37:39 -0700604 log.debug("Send EAP challenge response to supplicant on dev/port: {}/{}" +
605 " with MacAddress {} and Identifier {}",
606 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200607 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
608 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
609 outPacketSupp.add(eapPayload.getIdentifier());
Andrea Campanella76ae68d2020-10-14 11:16:37 +0200610 aaaStatisticsManager.getAaaStats().incrementPendingReqSupp();
Andrea Campanellac4781e62020-10-08 12:58:45 +0200611 //increasing packets send to server
612 machineStats.incrementTotalPacketsSent();
613 machineStats.incrementTotalOctetSent(eapPayload.getLength());
614 break;
615 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700616 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT for dev/port: {}/{}" +
617 " with MacAddress {} and Identifier {}",
618 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200619 //send an EAPOL - Success to the supplicant.
620 byte[] eapMessageSuccess =
621 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
622 try {
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700623 eapPayload = EAP.deserializer().deserialize(
624 eapMessageSuccess, 0, eapMessageSuccess.length);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200625 } catch (DeserializationException e) {
626 log.error(e.getMessage());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700627 break;
Andrea Campanellac4781e62020-10-08 12:58:45 +0200628 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700629
Andrea Campanellac4781e62020-10-08 12:58:45 +0200630 eth = buildEapolResponse(stateMachine.supplicantAddress(),
631 MacAddress.valueOf(nasMacAddress),
632 stateMachine.vlanId(),
633 EAPOL.EAPOL_PACKET,
634 eapPayload, stateMachine.priorityCode());
Matteo Scandoloe033c262020-10-14 11:37:39 -0700635 log.info("Send EAP success message to supplicant on dev/port: {}/{}" +
636 " with MacAddress {} and Identifier {}",
637 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200638 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
639 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
640
641 stateMachine.authorizeAccess();
642 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
643 //increasing packets send to server
644 machineStats.incrementTotalPacketsSent();
645 machineStats.incrementTotalOctetSent(eapPayload.getLength());
646 break;
647 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700648 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT for dev/port: {}/{}" +
649 " with MacAddress {} and Identifier {}",
650 supplicantCp.deviceId(), supplicantCp.port(), dstMac, radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200651 //send an EAPOL - Failure to the supplicant.
652 byte[] eapMessageFailure;
653 eapPayload = new EAP();
654 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
655 if (radiusAttrEap == null) {
656 eapPayload.setCode(EAP.FAILURE);
657 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
658 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
659 } else {
660 eapMessageFailure = radiusAttrEap.getValue();
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700661 try {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200662 eapPayload = EAP.deserializer().deserialize(
663 eapMessageFailure, 0, eapMessageFailure.length);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700664 } catch (DeserializationException e) {
665 log.error(e.getMessage());
666 break;
667 }
Andrea Campanellac4781e62020-10-08 12:58:45 +0200668 }
669 eth = buildEapolResponse(stateMachine.supplicantAddress(),
670 MacAddress.valueOf(nasMacAddress),
671 stateMachine.vlanId(),
672 EAPOL.EAPOL_PACKET,
673 eapPayload, stateMachine.priorityCode());
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700674 log.warn("Send EAP failure message to supplicant on dev/port: {}/{}" +
Matteo Scandoloe033c262020-10-14 11:37:39 -0700675 " with MacAddress {} and Identifier {}", supplicantCp.deviceId(), supplicantCp.port(),
676 dstMac, stateMachine.challengeIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200677 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
678 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
679
680 stateMachine.denyAccess();
681 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
682 //increasing packets send to server
683 machineStats.incrementTotalPacketsSent();
684 machineStats.incrementTotalOctetSent(eapPayload.getLength());
685 //pushing machine stats to kafka
686 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
687 aaaSupplicantStatsManager.getMachineStatsDelegate()
688 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE,
689 machineObj));
690 break;
691 default:
Matteo Scandoloe033c262020-10-14 11:37:39 -0700692 log.warn("Unknown RADIUS message received with code: {} for dev/port: {}/{}" +
693 " with MacAddress {} and Identifier {}",
694 radiusPacket.getCode(), supplicantCp.deviceId(), supplicantCp.port(), dstMac,
695 radiusPacket.getIdentifier() & 0xff);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200696 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
697 //increasing packets received to server
698 machineStats.incrementTotalPacketsReceived();
699 try {
700 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
701 } catch (DeserializationException e) {
702 log.error(e.getMessage());
703 break;
704 }
705 }
706 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700707 }
708
Ray Milkey967776a2015-10-07 14:37:17 -0700709 /**
710 * Send the ethernet packet to the supplicant.
711 *
712 * @param ethernetPkt the ethernet packet
713 * @param connectPoint the connect point to send out
714 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000715 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700716 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
717 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
718 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000719 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700720 if (log.isTraceEnabled()) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700721 log.trace("Sending eapol payload {} to supplicant at {} with MacAddress {}",
722 eap, connectPoint, ethernetPkt.getDestinationMAC());
Saurav Das987441a2018-09-18 16:33:47 -0700723 }
Ray Milkey967776a2015-10-07 14:37:17 -0700724 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000725 if (isChallengeResponse) {
726 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
727 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000728 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
729 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700730 }
731
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400732 @Override
733 public String toString() {
734 return ToStringBuilder.reflectionToString(this);
735 }
736
Jonathan Hart612651f2019-11-25 09:21:43 -0800737 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800738 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
Hardik Windlassd0b49692020-02-26 18:17:14 +0000739 return authentications.values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800740 }
741
742 @Override
743 public boolean removeAuthenticationStateByMac(MacAddress mac) {
744
Hardik Windlassd0b49692020-02-26 18:17:14 +0000745 Optional<AuthenticationRecord> r = authentications.values().stream()
746 .filter(v -> v.supplicantAddress().equals(mac))
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800747 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800748
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800749 if (r.isEmpty()) {
750 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800751 }
752
Hardik Windlassd0b49692020-02-26 18:17:14 +0000753 AuthenticationRecord removed =
754 authentications.remove(r.get().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800755
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800756 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800757 }
758
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800759 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800760 return stateMachines.get(sessionId);
761 }
762
763 private String sessionId(ConnectPoint cp) {
764 return cp.deviceId().toString() + cp.port().toString();
765 }
766
Ari Saha89831742015-06-26 10:31:48 -0700767 // our handler defined as a private inner class
768
769 /**
770 * Packet processor responsible for forwarding packets along their paths.
771 */
772 private class ReactivePacketProcessor implements PacketProcessor {
773 @Override
774 public void process(PacketContext context) {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200775 packetProcessorExecutor.execute(() -> {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700776 try {
777 // Extract the original Ethernet frame from the packet information
778 InboundPacket pkt = context.inPacket();
779 if (pkt == null) {
780 log.warn("Dropping inbound packet as it can't be parsed (inpacket)");
781 return;
782 }
783 Ethernet ethPkt = pkt.parsed();
784 if (ethPkt == null) {
785 log.warn("Dropping inbound packet as it can't be parsed (ethpacket)");
786 return;
787 }
Ari Saha89831742015-06-26 10:31:48 -0700788
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700789 EthType.EtherType pktType;
790 try {
791 short ethType = ethPkt.getEtherType();
792 pktType = EthType.EtherType.lookup(ethType);
793 } catch (Exception e) {
794 log.error("Exception while reading packet type", e);
795 return;
796 }
797
798 // identify if incoming packet comes from supplicant (EAP) or RADIUS
799 switch (pktType) {
800 case EAPOL:
801 if (log.isTraceEnabled()) {
802 log.trace("Received EAPOL supplicant packet from dev/port: {} with MacAddress {}",
803 context.inPacket().receivedFrom(), ethPkt.getSourceMAC());
804 }
805 handleSupplicantPacket(context.inPacket());
806 break;
807 default:
808 // any other packets let the specific implementation handle
809 if (log.isTraceEnabled()) {
810 log.trace("Received packet-in from RADIUS server {} in enclosing packet {} from "
811 + "dev/port: {} with MacAddress {}", ethPkt, context.inPacket(),
812 context.inPacket().receivedFrom(), ethPkt.getSourceMAC());
813 }
814 impl.handlePacketFromServer(context);
815 }
816 } catch (Exception e) {
817 log.error("Error while processing packet", e);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200818 }
819 });
Ari Saha89831742015-06-26 10:31:48 -0700820 }
821
Ray Milkey9eb293f2015-09-30 15:09:17 -0700822 /**
823 * Creates and initializes common fields of a RADIUS packet.
824 *
Ray Milkey967776a2015-10-07 14:37:17 -0700825 * @param stateMachine state machine for the request
Matteo Scandoloe033c262020-10-14 11:37:39 -0700826 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700827 * @return RADIUS packet
828 */
Ray Milkey967776a2015-10-07 14:37:17 -0700829 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700830 RADIUS radiusPayload =
831 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
832 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700833
834 // set Request Authenticator in StateMachine
835 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
836
Ray Milkey9eb293f2015-09-30 15:09:17 -0700837 radiusPayload.setIdentifier(identifier);
838 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700839 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700840
841 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Matteo Scandoloe033c262020-10-14 11:37:39 -0700842 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700843
844 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700845
846 return radiusPayload;
847 }
Ari Saha89831742015-06-26 10:31:48 -0700848
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700849 private void handleEapolStart(InboundPacket inPacket, StateMachine stateMachine) {
850
851 DeviceId deviceId = inPacket.receivedFrom().deviceId();
852 PortNumber portNumber = inPacket.receivedFrom().port();
853 Ethernet ethPkt = inPacket.parsed();
854 MacAddress srcMac = ethPkt.getSourceMAC();
855
856 log.debug("EAP packet: EAPOL_START from dev/port: {}/{} with MacAddress {}",
857 deviceId, portNumber, srcMac);
858 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
859 stateMachine.setSupplicantAddress(srcMac);
860 stateMachine.start();
861
862 aaaStatisticsManager.getAaaStats().incrementEapolStartReqRx();
863 //send an EAP Request/Identify to the supplicant
864 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
865 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
866 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
867 }
868 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
869 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
870 eapPayload, stateMachine.priorityCode());
871
872 stateMachine.setVlanId(ethPkt.getVlanID());
873 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
874 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
875 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
876 }
877
878 private void hangleEapolLogoff(InboundPacket inPacket, StateMachine stateMachine) {
879
880 DeviceId deviceId = inPacket.receivedFrom().deviceId();
881 PortNumber portNumber = inPacket.receivedFrom().port();
882 Ethernet ethPkt = inPacket.parsed();
883 MacAddress srcMac = ethPkt.getSourceMAC();
884
885 log.debug("EAP packet: EAPOL_LOGOFF from dev/port: {}/{} with MacAddress {}",
886 deviceId, portNumber, srcMac);
887 //posting the machine stat data for current supplicant device.
888 if (stateMachine.getSessionTerminateReason() == null ||
889 stateMachine.getSessionTerminateReason().equals("")) {
890 stateMachine.setSessionTerminateReason(
891 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
892 }
893 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
894 aaaSupplicantStatsManager.getMachineStatsDelegate()
895 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
896 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
897 stateMachine.logoff();
898 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
899 }
900 if (stateMachine.state() == StateMachine.STATE_IDLE) {
901 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
902 }
903 }
904
905 private void handleForgedEapolChallengeAuth(StateMachine stateMachine) {
906 stateMachine.requestAccess();
907
908 log.info("Forging EAP auth challenge");
909 byte[] challengeState = EapolPacketGenerator.hexStringToByteArray("19056d66190469d738db2f7dc1e02591");
910 EAP eapPayload = EapolPacketGenerator.forgeEapolChallengeAuth();
911
912 Ethernet eth = buildEapolResponse(stateMachine.supplicantAddress(),
913 MacAddress.valueOf(nasMacAddress),
914 stateMachine.vlanId(),
915 EAPOL.EAPOL_PACKET,
916 eapPayload, stateMachine.priorityCode());
917 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
918
919 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
920 MacAddress dstMac = stateMachine.supplicantAddress();
921 log.info("Send FORGED EAP auth challenge to supplicant {} on dev/port: {}/{} with MacAddress {}",
922 supplicantCp.deviceId(), supplicantCp.port(), dstMac);
923
924 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(),
925 true);
926
927 // NOTE do we care about stats?
928 }
929
930 private void handleForgedEapolSuccess(StateMachine stateMachine) {
931 ConnectPoint supplicantCp = stateMachine.supplicantConnectpoint();
932 MacAddress dstMac = stateMachine.supplicantAddress();
933 log.info("Forging EAP auth success");
934 EAP eapPayload = EapolPacketGenerator.forgeEapolSuccess();
935
936 Ethernet eth = buildEapolResponse(stateMachine.supplicantAddress(),
937 MacAddress.valueOf(nasMacAddress),
938 stateMachine.vlanId(),
939 EAPOL.EAPOL_PACKET,
940 eapPayload, stateMachine.priorityCode());
941 log.info("Send FORGED EAP success message to supplicant {} on dev/port: {}/{} with MacAddress {}",
942 supplicantCp.deviceId(), supplicantCp.port(), dstMac);
943 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
944 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
945
946 stateMachine.authorizeAccess();
947 }
948
949
Ari Saha89831742015-06-26 10:31:48 -0700950 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700951 * Handles PAE packets (supplicant).
952 *
953 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700954 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800955 private void handleSupplicantPacket(InboundPacket inPacket) {
Matteo Scandoloe033c262020-10-14 11:37:39 -0700956
Jonathan Harta46dddf2015-06-30 15:31:20 -0700957 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700958 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800959 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700960
Jonathan Harta46dddf2015-06-30 15:31:20 -0700961 DeviceId deviceId = inPacket.receivedFrom().deviceId();
962 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800963 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700964 EAPOL eapol = (EAPOL) ethPkt.getPayload();
Matteo Scandoloe033c262020-10-14 11:37:39 -0700965
Saurav Das987441a2018-09-18 16:33:47 -0700966 if (log.isTraceEnabled()) {
967 log.trace("Received EAPOL packet {} in enclosing packet {} from "
Matteo Scandoloe033c262020-10-14 11:37:39 -0700968 + "dev/port: {}/{} with MacAddress {} and type {}",
969 eapol, ethPkt, deviceId, portNumber, srcMac, eapol.getEapolType());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100970 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700971
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000972 short pktlen = eapol.getPacketLength();
973 byte[] eapPayLoadBuffer = eapol.serialize();
974 int len = eapPayLoadBuffer.length;
975 if (len != (HEADER_LENGTH + pktlen)) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700976 log.warn("Invalid EAPOL pkt length {} (shoudl be {}) for packet {} from dev/port: {}/{} " +
977 "with MacAddress {}, dropping it",
978 len, HEADER_LENGTH + pktlen, eapol, deviceId, portNumber, srcMac);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000979 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
980 return;
981 }
982 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700983 log.warn("Invalid EAPOL Type {} for packet {} from dev/port: {}/{} with MacAddress {}, dropping it",
Matteo Scandoloe033c262020-10-14 11:37:39 -0700984 eapol.getEapolType(), eapol, deviceId, portNumber, srcMac);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000985 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
986 return;
987 }
988 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
989 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
990 }
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700991 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id ->
992 new StateMachine(id, serverStatusAndStateMachineTimeoutExecutor));
Jonathan Hart612651f2019-11-25 09:21:43 -0800993 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700994
Ari Saha89831742015-06-26 10:31:48 -0700995 switch (eapol.getEapolType()) {
996 case EAPOL.EAPOL_START:
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -0700997 handleEapolStart(inPacket, stateMachine);
Ari Saha89831742015-06-26 10:31:48 -0700998 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800999 case EAPOL.EAPOL_LOGOFF:
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001000 hangleEapolLogoff(inPacket, stateMachine);
Qianqian Hub55a1ac2015-12-23 20:44:48 +08001001 break;
Ari Saha89831742015-06-26 10:31:48 -07001002 case EAPOL.EAPOL_PACKET:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001003
Ray Milkey9eb293f2015-09-30 15:09:17 -07001004 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -07001005 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +00001006 Byte identifier = new Byte(eapPacket.getIdentifier());
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001007
Matteo Scandoloe033c262020-10-14 11:37:39 -07001008 log.debug("EAP packet: EAPOL_PACKET from dev/port: {}/{} with MacAddress {} with Identifier {}",
1009 deviceId, portNumber, srcMac, identifier.doubleValue());
Jonathan Hart612651f2019-11-25 09:21:43 -08001010
Ari Saha89831742015-06-26 10:31:48 -07001011 byte dataType = eapPacket.getDataType();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001012
Ari Saha89831742015-06-26 10:31:48 -07001013 switch (dataType) {
Ray Milkey9eb293f2015-09-30 15:09:17 -07001014 case EAP.ATTR_IDENTITY:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001015 handleAttrIdentity(inPacket, srcMac, deviceId, portNumber,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001016 eapol, stateMachine, eapPacket, sessionId);
Ray Milkey9eb293f2015-09-30 15:09:17 -07001017 break;
Ari Saha89831742015-06-26 10:31:48 -07001018 case EAP.ATTR_MD5:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001019 handleMD5(inPacket, srcMac, deviceId, portNumber, stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001020 eapPacket, identifier, sessionId);
Ari Saha89831742015-06-26 10:31:48 -07001021 break;
1022 case EAP.ATTR_TLS:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001023 handleTls(inPacket, srcMac, deviceId, portNumber, stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001024 eapPacket, identifier, sessionId);
Ari Saha89831742015-06-26 10:31:48 -07001025 break;
1026 default:
Matteo Scandoloe033c262020-10-14 11:37:39 -07001027 log.warn("Unknown EAP packet type from dev/port: {}/{} with MacAddress {} and " +
1028 "Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
Ari Saha89831742015-06-26 10:31:48 -07001029 return;
1030 }
1031 break;
1032 default:
Andrea Campanellac4781e62020-10-08 12:58:45 +02001033 log.debug("Skipping EAPOL message {} from dev/port: {}/{} with MacAddress {}",
1034 eapol.getEapolType(), deviceId, portNumber, srcMac);
Ari Saha89831742015-06-26 10:31:48 -07001035 }
Shubham Sharma1f193582019-07-11 12:12:41 +00001036 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
1037 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -07001038 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001039
1040 private void handleAttrIdentity(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1041 PortNumber portNumber, EAPOL eapol, StateMachine stateMachine,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001042 EAP eapPacket, String sessionId) {
Matteo Scandoloe033c262020-10-14 11:37:39 -07001043
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001044 if (forgeEapolPackets) {
1045 handleForgedEapolChallengeAuth(stateMachine);
1046 return;
1047 } else {
1048 // get identifier for request and store mapping to session ID
1049 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1050 if (radiusIdentifier == null) {
1051 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1052 "with MacAddress {}, dropping packet",
1053 deviceId, portNumber, srcMac);
1054 return;
1055 }
1056 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY from dev/port: {}/{} with MacAddress {}" +
1057 " and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1058 //Setting the time of this response from RG, only when its not a re-transmission.
1059 if (stateMachine.getLastPacketReceivedTime() == 0) {
1060 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
1061 }
1062 // request id access to RADIUS
1063 stateMachine.setUsername(eapPacket.getData());
Matteo Scandoloe033c262020-10-14 11:37:39 -07001064
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001065 RADIUS radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
1066 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
1067 radiusPayload.addMessageAuthenticator(radiusSecret);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001068
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001069 if (log.isTraceEnabled()) {
1070 log.trace("Sending ATTR_IDENTITY packet to RADIUS for supplicant at dev/port: " +
1071 "{}/{} with MacAddress {} and Identifier {}", deviceId, portNumber,
1072 srcMac, radiusIdentifier.identifier() & 0xff);
1073 }
1074
1075 sendRadiusPacket(radiusPayload, inPacket);
1076 stateMachine.setWaitingForRadiusResponse(true);
1077 aaaStatisticsManager.getAaaStats().incrementRadiusReqIdTx();
1078 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
1079 // change the state to "PENDING"
1080 if (stateMachine.state() == StateMachine.STATE_PENDING) {
1081 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
1082 stateMachine.incrementTotalPacketsSent();
1083 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
1084 }
1085 stateMachine.requestAccess();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001086 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001087 }
1088
1089 private void handleMD5(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1090 PortNumber portNumber, StateMachine stateMachine, EAP eapPacket,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001091 Byte identifier, String sessionId) {
1092 // get identifier for request and store mapping to session ID
1093 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1094 if (radiusIdentifier == null) {
1095 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1096 "with MacAddress {}, dropping packet",
1097 deviceId, portNumber, srcMac);
1098 return;
1099 }
1100
Matteo Scandoloe033c262020-10-14 11:37:39 -07001101 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5 from dev/port: {}/{} with MacAddress {}" +
1102 " and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1103 // verify if the EAP identifier corresponds to the
1104 // challenge identifier from the client state
1105 // machine.
1106 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
1107 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
1108 //send the RADIUS challenge response
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001109 if (forgeEapolPackets) {
1110 handleForgedEapolSuccess(stateMachine);
1111 } else {
1112 RADIUS radiusPayload = getRadiusPayload(stateMachine,
1113 radiusIdentifier.identifier(), eapPacket);
1114 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001115
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001116 if (stateMachine.challengeState() != null) {
1117 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
1118 stateMachine.challengeState());
1119 }
1120 radiusPayload.addMessageAuthenticator(radiusSecret);
1121 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1122 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1123 outPacketSupp.remove(identifier);
1124 }
1125 if (log.isTraceEnabled()) {
1126 log.trace("Sending ATTR_MD5 packet to RADIUS for supplicant at dev/port: {}/{}" +
1127 " with MacAddress {} and Identifier {}", deviceId, portNumber, srcMac,
1128 radiusIdentifier.identifier() & 0xff);
1129 }
1130 sendRadiusPacket(radiusPayload, inPacket);
1131 stateMachine.setWaitingForRadiusResponse(true);
1132 aaaStatisticsManager.getAaaStats().incrementRadiusReqChallengeTx();
1133 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Matteo Scandoloe033c262020-10-14 11:37:39 -07001134 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001135 } else {
1136 log.error("eapolIdentifier {} and stateMachine Identifier {} do not " +
1137 "correspond for packet from dev/port: {}/{} with MacAddress {}",
1138 eapPacket.getIdentifier() & 0xff, stateMachine.challengeIdentifier() & 0xff,
1139 deviceId, portNumber, srcMac);
1140 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
1141 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1142 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1143 outPacketSupp.remove(identifier);
1144 }
1145 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
1146 }
1147 }
1148
1149
1150 private void handleTls(InboundPacket inPacket, MacAddress srcMac, DeviceId deviceId,
1151 PortNumber portNumber, StateMachine stateMachine, EAP eapPacket,
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001152 Byte identifier, String sessionId) {
1153 // get identifier for request and store mapping to session ID
1154 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
1155
1156 if (radiusIdentifier == null) {
1157 log.warn("Cannot get identifier supplicant at dev/port: {}/{} " +
1158 "with MacAddress {}, dropping packet", deviceId, portNumber, srcMac);
1159 return;
1160 }
Matteo Scandoloe033c262020-10-14 11:37:39 -07001161 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS from dev/port: {}/{} with MacAddress {} " +
1162 "and Identifier {}", deviceId, portNumber, srcMac, eapPacket.getIdentifier() & 0xff);
1163 // request id access to RADIUS
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -07001164 RADIUS radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Matteo Scandoloe033c262020-10-14 11:37:39 -07001165 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
1166 if (stateMachine.challengeState() != null) {
1167 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
1168 stateMachine.challengeState());
1169 }
1170 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
1171 radiusPayload.addMessageAuthenticator(radiusSecret);
1172 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
1173 aaaStatisticsManager.getAaaStats().decrementPendingReqSupp();
1174 outPacketSupp.remove(identifier);
1175 }
1176 if (log.isTraceEnabled()) {
1177 log.trace("Sending ATTR_TLS packet to RADIUS for supplicant at dev/port: {}/{} with " +
1178 "MacAddress {} and Identifier {}", deviceId, portNumber, srcMac,
1179 radiusIdentifier.identifier() & 0xff);
1180 }
1181 sendRadiusPacket(radiusPayload, inPacket);
1182 stateMachine.setWaitingForRadiusResponse(true);
1183 aaaStatisticsManager.getAaaStats().incrementRadiusReqChallengeTx();
1184 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
1185 if (stateMachine.state() != StateMachine.STATE_PENDING) {
1186 stateMachine.requestAccess();
1187 }
1188 }
Ray Milkey967776a2015-10-07 14:37:17 -07001189 }
1190
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001191 /**
Jonathan Hart5db44532018-07-12 18:13:54 -07001192 * Delegate allowing the StateMachine to notify us of events.
1193 */
1194 private class InternalStateMachineDelegate implements StateMachineDelegate {
1195
1196 @Override
1197 public void notify(AuthenticationEvent authenticationEvent) {
1198 log.info("Auth event {} for {}",
Matteo Scandoloe033c262020-10-14 11:37:39 -07001199 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -08001200
1201 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
1202 handleStateMachineTimeout(authenticationEvent.subject());
1203 }
1204
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001205 AuthenticationRecord record = authenticationEvent.authenticationRecord();
1206 if (record == null) {
1207 authentications.remove(authenticationEvent.subject());
1208 } else {
1209 authentications.put(authenticationEvent.subject(), record);
1210 }
1211
Jonathan Hart5db44532018-07-12 18:13:54 -07001212 post(authenticationEvent);
1213 }
1214 }
1215
Jonathan Hart612651f2019-11-25 09:21:43 -08001216 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
1217 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
Andrea Campanellae66466a2020-02-03 14:05:45 +00001218 //pushing captured machine stats to kafka
1219 stateMachine.setSessionTerminateReason("Time out");
1220 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
1221 .getSupplicantStats(stateMachine);
1222 aaaSupplicantStatsManager.getMachineStatsDelegate()
1223 .notify(new AaaMachineStatisticsEvent(
1224 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
1225
Jonathan Hart612651f2019-11-25 09:21:43 -08001226 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
1227 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
1228 }
1229
1230 StateMachine.deleteStateMachineMapping(stateMachine);
1231 }
1232
Jonathan Hart5db44532018-07-12 18:13:54 -07001233 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001234 * Configuration Listener, handles change in configuration.
1235 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001236 private class InternalConfigListener implements NetworkConfigListener {
1237
1238 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -08001239 * Reconfigures the AAA application according to the
1240 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001241 *
1242 * @param cfg configuration object
1243 */
Jonathan Hart092dfb22015-11-16 23:05:21 -08001244 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001245 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001246
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001247 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -08001248 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001249 } else {
1250 newCfg = cfg;
1251 }
1252 if (newCfg.nasIp() != null) {
1253 nasIpAddress = newCfg.nasIp();
1254 }
1255 if (newCfg.radiusIp() != null) {
1256 radiusIpAddress = newCfg.radiusIp();
1257 }
1258 if (newCfg.radiusMac() != null) {
1259 radiusMacAddress = newCfg.radiusMac();
1260 }
1261 if (newCfg.nasMac() != null) {
1262 nasMacAddress = newCfg.nasMac();
1263 }
Andrea Campanellac4781e62020-10-08 12:58:45 +02001264 if (newCfg.radiusSecret() != null && !newCfg.radiusSecret().equals(radiusSecret)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001265 radiusSecret = newCfg.radiusSecret();
Andrea Campanellac4781e62020-10-08 12:58:45 +02001266 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001267 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001268
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301269 boolean reconfigureCustomizer = false;
1270 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
1271 customizer = newCfg.radiusPktCustomizer();
1272 configurePacketCustomizer();
1273 reconfigureCustomizer = true;
1274 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001275
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301276 if (radiusConnectionType == null
1277 || reconfigureCustomizer
1278 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
1279 radiusConnectionType = newCfg.radiusConnectionType();
1280 if (impl != null) {
1281 impl.withdrawIntercepts();
1282 impl.clearLocalState();
1283 }
1284 configureRadiusCommunication();
1285 impl.initializeLocalState(newCfg);
1286 impl.requestIntercepts();
1287 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001288 impl.clearLocalState();
1289 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -07001290 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001291 }
1292
1293 @Override
1294 public void event(NetworkConfigEvent event) {
1295
1296 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1297 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001298 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001299
Jonathan Hart092dfb22015-11-16 23:05:21 -08001300 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001301 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001302
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001303 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001304 }
1305 }
1306 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001307
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001308 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1309 @Override
1310 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1311 if (event.type() == MapEvent.Type.REMOVE) {
1312 // remove local state machine if user has requested remove
1313 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1314 if (sm != null) {
1315 sm.stop();
1316 }
1317 }
1318 }
1319 }
1320
Amit Ghoshf739be52017-09-21 15:49:37 +01001321 private class InternalDeviceListener implements DeviceListener {
1322 @Override
1323 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001324 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001325 switch (event.type()) {
1326 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001327 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001328 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001329 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
Hardik Windlass75c67712020-02-21 10:57:20 +00001330
Girish Kumar064084c2020-02-04 08:32:46 +00001331 flushStateMachineSession(sessionId,
Matteo Scandoloe033c262020-10-14 11:37:39 -07001332 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001333
Girish Kumar064084c2020-02-04 08:32:46 +00001334 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001335 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001336 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001337 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001338 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001339
Amit Ghoshf739be52017-09-21 15:49:37 +01001340 default:
1341 return;
1342 }
1343 }
Girish Kumar064084c2020-02-04 08:32:46 +00001344
Andrea Campanellabba33672020-02-11 14:03:01 +01001345 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1346 Set<String> associatedSessions = Sets.newHashSet();
1347 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1348 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1349 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1350 associatedSessions.add(stateMachineEntry.getKey());
1351 }
1352 }
1353
1354 for (String session : associatedSessions) {
1355 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1356 flushStateMachineSession(session,
Matteo Scandoloe033c262020-10-14 11:37:39 -07001357 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
Andrea Campanellabba33672020-02-11 14:03:01 +01001358 }
1359 }
1360
Girish Kumar064084c2020-02-04 08:32:46 +00001361 private void flushStateMachineSession(String sessionId, String terminationReason) {
1362 StateMachine stateMachine = stateMachines.get(sessionId);
Girish Kumare5a1aa92020-02-14 14:08:54 +00001363 if (stateMachine == null) {
1364 // No active AAA sessions for this UNI port
1365 log.debug("No Active AAA Session found with Id {}", sessionId);
1366 return;
Girish Kumar064084c2020-02-04 08:32:46 +00001367 }
1368
Hardik Windlass9a09b832020-02-25 11:45:35 +00001369 authentications.remove(stateMachine.supplicantConnectpoint());
Girish Kumare5a1aa92020-02-14 14:08:54 +00001370 stateMachine.setSessionTerminateReason(terminationReason);
1371
Girish Kumar064084c2020-02-04 08:32:46 +00001372 //pushing captured machine stats to kafka
1373 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1374 aaaSupplicantStatsManager.getMachineStatsDelegate()
Matteo Scandoloe033c262020-10-14 11:37:39 -07001375 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Girish Kumar064084c2020-02-04 08:32:46 +00001376 StateMachine removed = stateMachines.remove(sessionId);
Shubham Sharma8d7a9822020-01-28 10:04:01 +00001377
Girish Kumar064084c2020-02-04 08:32:46 +00001378 if (removed != null) {
1379 StateMachine.deleteStateMachineMapping(removed);
1380 }
1381 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001382 }
Girish Kumar064084c2020-02-04 08:32:46 +00001383
Shubham Sharma4900ce62019-06-19 14:18:50 +00001384 private class ServerStatusChecker implements Runnable {
1385 @Override
1386 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001387 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001388 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001389 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001390 radiusOperationalStatusService.getRadiusOprStDelegate()
Matteo Scandoloe033c262020-10-14 11:37:39 -07001391 .notify(new RadiusOperationalStatusEvent(
1392 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1393 radiusOperationalStatusService.
1394 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001395 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001396
1397 }
Shubham Sharma544ffa22020-02-13 06:41:02 +00001398
1399 @Override
1400 public AaaSupplicantMachineStats getSupplicantMachineStats(String sessionId) {
1401 StateMachine aaaSupplicantMachine = stateMachines.get(sessionId);
1402 if (aaaSupplicantMachine != null) {
1403 return aaaSupplicantStatsManager.getSupplicantStats(aaaSupplicantMachine);
1404 } else {
1405 return null;
1406 }
1407 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001408}