blob: c2e62ebe7a35035e2cbbce40d19020135c073d30 [file] [log] [blame]
Ari Saha89831742015-06-26 10:31:48 -07001/*
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01002 * Copyright 2017-present Open Networking Foundation
Ari Saha89831742015-06-26 10:31:48 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matteo Scandolocf847b82019-04-26 15:00:00 -070016package org.opencord.aaa.impl;
Ari Saha89831742015-06-26 10:31:48 -070017
Shubham Sharma4900ce62019-06-19 14:18:50 +000018import com.google.common.base.Strings;
Jonathan Hart612651f2019-11-25 09:21:43 -080019import com.google.common.collect.Maps;
Girish Kumar064084c2020-02-04 08:32:46 +000020import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
21import static org.slf4j.LoggerFactory.getLogger;
22
23import com.google.common.collect.Sets;
24import java.net.InetAddress;
25import java.net.UnknownHostException;
26import java.nio.ByteBuffer;
27import java.util.Dictionary;
28import java.util.HashSet;
29import java.util.Arrays;
30import java.util.List;
31import java.util.Set;
32import java.util.Map.Entry;
33
Jonathan Hart932bedc2018-07-12 13:46:09 -070034import org.apache.commons.lang3.builder.ToStringBuilder;
Jonathan Hart4731dd92018-05-02 17:30:05 -070035import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070036import org.onlab.packet.EAP;
37import org.onlab.packet.EAPOL;
38import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070039import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070040import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070041import org.onlab.packet.RADIUS;
42import org.onlab.packet.RADIUSAttribute;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080043import org.onlab.util.KryoNamespace;
kartikey dubeye1545422019-05-22 12:53:45 +000044import org.onlab.util.Tools;
45import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070046import org.onosproject.core.ApplicationId;
47import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070048import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010049import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070050import org.onosproject.net.ConnectPoint;
51import org.onosproject.net.DeviceId;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080052import org.onosproject.net.ElementId;
Ari Saha89831742015-06-26 10:31:48 -070053import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070054import org.onosproject.net.config.ConfigFactory;
55import org.onosproject.net.config.NetworkConfigEvent;
56import org.onosproject.net.config.NetworkConfigListener;
57import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010058import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010060import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070061import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070062import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070063import org.onosproject.net.packet.DefaultOutboundPacket;
64import org.onosproject.net.packet.InboundPacket;
65import org.onosproject.net.packet.OutboundPacket;
66import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070067import org.onosproject.net.packet.PacketProcessor;
68import org.onosproject.net.packet.PacketService;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080069import org.onosproject.store.service.ConsistentMap;
70import org.onosproject.store.service.MapEvent;
71import org.onosproject.store.service.MapEventListener;
72import org.onosproject.store.service.Serializer;
73import org.onosproject.store.service.StorageService;
74import org.onosproject.store.service.Versioned;
Matteo Scandolocf847b82019-04-26 15:00:00 -070075import org.opencord.aaa.AaaConfig;
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +000076import org.opencord.aaa.AaaMachineStatisticsEvent;
77import org.opencord.aaa.AaaMachineStatisticsService;
78import org.opencord.aaa.AaaSupplicantMachineStats;
Matteo Scandolocf847b82019-04-26 15:00:00 -070079import org.opencord.aaa.AuthenticationEvent;
80import org.opencord.aaa.AuthenticationEventListener;
Jonathan Hart612651f2019-11-25 09:21:43 -080081import org.opencord.aaa.AuthenticationRecord;
Matteo Scandolocf847b82019-04-26 15:00:00 -070082import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000083import org.opencord.aaa.AuthenticationStatisticsEvent;
84import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070085import org.opencord.aaa.RadiusCommunicator;
Shubham Sharma4900ce62019-06-19 14:18:50 +000086import org.opencord.aaa.RadiusOperationalStatusEvent;
87import org.opencord.aaa.RadiusOperationalStatusService;
88import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
Matteo Scandolocf847b82019-04-26 15:00:00 -070089import org.opencord.aaa.StateMachineDelegate;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000090import org.opencord.sadis.BaseInformationService;
91import org.opencord.sadis.SadisService;
92import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000093import org.osgi.service.component.ComponentContext;
Carmelo Cascone58b53292019-09-30 12:35:31 -070094import org.osgi.service.component.annotations.Activate;
Shubham Sharma4900ce62019-06-19 14:18:50 +000095import org.osgi.service.component.annotations.Component;
96import org.osgi.service.component.annotations.Deactivate;
97import org.osgi.service.component.annotations.Modified;
98import org.osgi.service.component.annotations.Reference;
99import org.osgi.service.component.annotations.ReferenceCardinality;
Ari Saha89831742015-06-26 10:31:48 -0700100import org.slf4j.Logger;
101
Shubham Sharma4900ce62019-06-19 14:18:50 +0000102import javax.crypto.Mac;
103import javax.crypto.spec.SecretKeySpec;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800104import java.net.URI;
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800105import java.util.Optional;
Jonathan Hart612651f2019-11-25 09:21:43 -0800106import java.util.concurrent.ConcurrentMap;
kartikey dubeye1545422019-05-22 12:53:45 +0000107import java.util.concurrent.Executors;
108import java.util.concurrent.ScheduledExecutorService;
109import java.util.concurrent.ScheduledFuture;
110import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000111
Shubham Sharma4900ce62019-06-19 14:18:50 +0000112import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION;
113import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
114import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT;
115import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
116import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_PERIOD;
117import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_PERIOD_DEFAULT;
118import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE;
119import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE_DEFAULT;
Carmelo Cascone58b53292019-09-30 12:35:31 -0700120
Ari Saha89831742015-06-26 10:31:48 -0700121/**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700122 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -0700123 */
Carmelo Cascone58b53292019-09-30 12:35:31 -0700124@Component(immediate = true, property = {
Shubham Sharma4900ce62019-06-19 14:18:50 +0000125 STATISTICS_GENERATION_PERIOD + ":Integer=" + STATISTICS_GENERATION_PERIOD_DEFAULT,
126 OPERATIONAL_STATUS_SERVER_EVENT_GENERATION + ":Integer=" + OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT,
127 OPERATIONAL_STATUS_SERVER_TIMEOUT + ":Integer=" + OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT,
128 STATUS_SERVER_MODE + ":String=" + STATUS_SERVER_MODE_DEFAULT,
Carmelo Cascone58b53292019-09-30 12:35:31 -0700129})
Jonathan Hart5db44532018-07-12 18:13:54 -0700130public class AaaManager
131 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
132 implements AuthenticationService {
133
Charles Chandf7ff862017-01-20 11:22:05 -0800134 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -0700135
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700136 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700137
Carmelo Cascone58b53292019-09-30 12:35:31 -0700138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700139 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700140
Carmelo Cascone58b53292019-09-30 12:35:31 -0700141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800142 protected StorageService storageService;
143
144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700145 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700146
Carmelo Cascone58b53292019-09-30 12:35:31 -0700147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700148 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700149
Carmelo Cascone58b53292019-09-30 12:35:31 -0700150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100151 protected DeviceService deviceService;
152
Carmelo Cascone58b53292019-09-30 12:35:31 -0700153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000154 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100155
Carmelo Cascone58b53292019-09-30 12:35:31 -0700156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100157 protected MastershipService mastershipService;
158
Carmelo Cascone58b53292019-09-30 12:35:31 -0700159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000160 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000161
Carmelo Cascone58b53292019-09-30 12:35:31 -0700162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000163 protected AaaMachineStatisticsService aaaSupplicantStatsManager;
164
165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
kartikey dubeye1545422019-05-22 12:53:45 +0000166 protected ComponentConfigService cfgService;
167
Shubham Sharma4900ce62019-06-19 14:18:50 +0000168 @Reference(cardinality = ReferenceCardinality.MANDATORY)
169 protected RadiusOperationalStatusService radiusOperationalStatusService;
170
kartikey dubeye1545422019-05-22 12:53:45 +0000171 protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
172 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100173 private final DeviceListener deviceListener = new InternalDeviceListener();
174
Shubham Sharma4900ce62019-06-19 14:18:50 +0000175 // Properties
176 private int statisticsGenerationPeriodInSeconds = STATISTICS_GENERATION_PERIOD_DEFAULT;
177 private int operationalStatusEventGenerationPeriodInSeconds = OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
178 private int operationalStatusServerTimeoutInSeconds = OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
179 protected String operationalStatusEvaluationMode = STATUS_SERVER_MODE_DEFAULT;
kartikey dubeye1545422019-05-22 12:53:45 +0000180
Jonathan Hart612651f2019-11-25 09:21:43 -0800181 private IdentifierManager idManager;
182
183 private ConcurrentMap<String, StateMachine> stateMachines;
184
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800185 private ConsistentMap<ConnectPoint, AuthenticationRecord> authentications;
186
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700187 // NAS IP address
188 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100189
190 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700191 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100192
193 // Parsed RADIUS server addresses
194 protected InetAddress radiusIpAddress;
195
196 // MAC address of RADIUS server or net hop router
197 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700198
199 // RADIUS server secret
200 protected String radiusSecret;
201
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100202 // bindings
203 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700204
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700205 // our application-specific event handler
206 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700207
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700208 // our unique identifier
209 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700210
Shubham Sharma1e43c562019-06-19 14:18:12 +0000211 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
212 protected int cleanupTimerTimeOutInMins;
213
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100214 // Setup specific customization/attributes on the RADIUS packets
215 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700216
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100217 // packet customizer to use
218 private String customizer;
219
220 // Type of connection to use to communicate with Radius server, options are
221 // "socket" or "packet_out"
222 private String radiusConnectionType;
223
Jonathan Hart5db44532018-07-12 18:13:54 -0700224 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100225 // server, socket based or packet_out based
226 RadiusCommunicator impl = null;
227
228 // latest configuration
229 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700230
kartikey dubeye1545422019-05-22 12:53:45 +0000231 ScheduledFuture<?> scheduledFuture;
Shubham Sharma4900ce62019-06-19 14:18:50 +0000232 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000233 ScheduledExecutorService executor;
234 String configuredAaaServerAddress;
235 HashSet<Byte> outPacketSet = new HashSet<Byte>();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000236 HashSet<Byte> outPacketSupp = new HashSet<Byte>();
237 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
238 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700239 // Configuration properties factory
240 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800241 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
242 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700243 "AAA") {
244 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800245 public AaaConfig createConfig() {
246 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700247 }
248 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700249
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700250 // Listener for config changes
251 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700252
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800253 private final InternalMapEventListener mapListener = new InternalMapEventListener();
254
Jonathan Hart5db44532018-07-12 18:13:54 -0700255 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
256
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700257 /**
258 * Builds an EAPOL packet based on the given parameters.
259 *
260 * @param dstMac destination MAC address
261 * @param srcMac source MAC address
262 * @param vlan vlan identifier
263 * @param eapolType EAPOL type
264 * @param eap EAP payload
265 * @return Ethernet frame
266 */
267 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100268 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700269
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700270 Ethernet eth = new Ethernet();
271 eth.setDestinationMACAddress(dstMac.toBytes());
272 eth.setSourceMACAddress(srcMac.toBytes());
273 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
274 if (vlan != Ethernet.VLAN_UNTAGGED) {
275 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100276 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700277 }
278 //eapol header
279 EAPOL eapol = new EAPOL();
280 eapol.setEapolType(eapolType);
281 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700282
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700283 //eap part
284 eapol.setPayload(eap);
285
286 eth.setPayload(eapol);
287 eth.setPad(true);
288 return eth;
289 }
Ari Saha89831742015-06-26 10:31:48 -0700290
Ari Saha89831742015-06-26 10:31:48 -0700291 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000292 public void activate(ComponentContext context) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800293 idManager = new IdentifierManager();
294 stateMachines = Maps.newConcurrentMap();
Charles Chandf7ff862017-01-20 11:22:05 -0800295 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800296
297 KryoNamespace authSerializer = KryoNamespace.newBuilder()
298 .register(byte[].class)
299 .register(String.class)
300 .register(long.class)
301 .register(boolean.class)
302 .register(URI.class)
303 .register(DeviceId.class)
304 .register(ElementId.class)
305 .register(PortNumber.class)
306 .register(ConnectPoint.class)
307 .register(MacAddress.class)
308 .register(AuthenticationRecord.class)
309 .build();
310
311 authentications = storageService.<ConnectPoint, AuthenticationRecord>consistentMapBuilder()
312 .withApplicationId(appId)
313 .withName("authentications")
314 .withSerializer(Serializer.using(authSerializer))
315 .build();
316 authentications.addListener(mapListener);
317
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);
kartikey dubeye1545422019-05-22 12:53:45 +0000338 authenticationStatisticsPublisher =
339 new AuthenticationStatisticsEventPublisher();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000340 executor = Executors.newScheduledThreadPool(3);
341
kartikey dubeye1545422019-05-22 12:53:45 +0000342 scheduledFuture = executor.scheduleAtFixedRate(authenticationStatisticsPublisher,
Shubham Sharma4900ce62019-06-19 14:18:50 +0000343 0, statisticsGenerationPeriodInSeconds, TimeUnit.SECONDS);
344 scheduledStatusServerChecker = executor.scheduleAtFixedRate(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);
kartikey dubeye1545422019-05-22 12:53:45 +0000360 scheduledFuture.cancel(true);
Shubham Sharma4900ce62019-06-19 14:18:50 +0000361 scheduledStatusServerChecker.cancel(true);
kartikey dubeye1545422019-05-22 12:53:45 +0000362 executor.shutdown();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800363
364 authentications.removeListener(mapListener);
365
Jian Li13c67162015-12-09 13:20:34 -0800366 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -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
372 String s = Tools.get(properties, "statisticsGenerationPeriodInSeconds");
373 statisticsGenerationPeriodInSeconds = Strings.isNullOrEmpty(s) ? STATISTICS_GENERATION_PERIOD_DEFAULT
374 : Integer.parseInt(s.trim());
375
376 s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
377 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
378 ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
379 : Integer.parseInt(s.trim());
380
381 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
382 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
383 : Integer.parseInt(s.trim());
384
385 s = Tools.get(properties, "operationalStatusEvaluationMode");
386 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
387
388 radiusOperationalStatusService
389 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
390 RadiusOperationalStatusEvaluationMode newEvaluationMode =
391 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
392 if (newEvaluationMode != null) {
393 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
394 operationalStatusEvaluationMode = newEvaluationModeString;
395 } else {
396 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
397 }
kartikey dubeye1545422019-05-22 12:53:45 +0000398 }
399
Shubham Sharmacf5e5032019-11-26 11:09:21 +0000400 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530401 if (radiusConnectionType.toLowerCase().equals("socket")) {
402 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
403 } else {
404 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
405 deviceService, subsService, pktCustomizer, this);
406 }
407 }
408
409 private void configurePacketCustomizer() {
410 switch (customizer.toLowerCase()) {
411 case "sample":
412 pktCustomizer = new SamplePacketCustomizer(customInfo);
413 log.info("Created SamplePacketCustomizer");
414 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800415 case "att":
416 pktCustomizer = new AttPacketCustomizer(customInfo);
417 log.info("Created AttPacketCustomizer");
418 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530419 default:
420 pktCustomizer = new PacketCustomizer(customInfo);
421 log.info("Created default PacketCustomizer");
422 break;
423 }
424 }
425
kartikey dubeye1545422019-05-22 12:53:45 +0000426 private void getConfiguredAaaServerAddress() {
427 try {
428 InetAddress address;
429 if (newCfg.radiusHostName() != null) {
430 address = InetAddress.getByName(newCfg.radiusHostName());
431 } else {
432 address = newCfg.radiusIp();
433 }
434
435 configuredAaaServerAddress = address.getHostAddress();
436 } catch (UnknownHostException uhe) {
437 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
438 }
439 }
440
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000441 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
442 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000443 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
444 }
445 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000446
447 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
448 byte[] newHash = new byte[16];
449 Arrays.fill(newHash, (byte) 0);
450 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
451 byte[] authenticator = radiusPacket.getAuthenticator();
452 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
453 radiusPacket.setAuthenticator(requestAuthenticator);
454 // Calculate the MD5 HMAC based on the message
455 try {
456 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
457 Mac mac = Mac.getInstance("HmacMD5");
458 mac.init(keySpec);
459 newHash = mac.doFinal(radiusPacket.serialize());
460 } catch (Exception e) {
461 log.error("Failed to generate message authenticator: {}", e.getMessage());
462 }
463 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
464 radiusPacket.setAuthenticator(authenticator);
465 // Compare the calculated Message-Authenticator with the one in the message
466 return Arrays.equals(newHash, messageAuthenticator);
467 }
kartikey dubeye1545422019-05-22 12:53:45 +0000468 public void checkForPacketFromUnknownServer(String hostAddress) {
469 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000470 getConfiguredAaaServerAddress();
471 if (!hostAddress.equals(configuredAaaServerAddress)) {
472 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
473 }
kartikey dubeye1545422019-05-22 12:53:45 +0000474 }
475 }
476
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100477 /**
478 * Send RADIUS packet to the RADIUS server.
479 *
480 * @param radiusPacket RADIUS packet to be sent to server.
481 * @param inPkt Incoming EAPOL packet
482 */
483 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000484 outPacketSet.add(radiusPacket.getIdentifier());
485 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
486 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000487 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100488 impl.sendRadiusPacket(radiusPacket, inPkt);
489 }
Ray Milkey967776a2015-10-07 14:37:17 -0700490
Jonathan Hart612651f2019-11-25 09:21:43 -0800491 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100492 * Handles RADIUS packets.
493 *
494 * @param radiusPacket RADIUS packet coming from the RADIUS server.
Jonathan Hart4731dd92018-05-02 17:30:05 -0700495 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100496 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800497 public void handleRadiusPacket(RADIUS radiusPacket) throws DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700498 if (log.isTraceEnabled()) {
499 log.trace("Received RADIUS packet {}", radiusPacket);
500 }
Shubham Sharma4900ce62019-06-19 14:18:50 +0000501 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
502 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
503 return;
504 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800505
506 RequestIdentifier identifier = RequestIdentifier.of(radiusPacket.getIdentifier());
507 String sessionId = idManager.getSessionId(identifier);
508
509 if (sessionId == null) {
510 log.error("Invalid packet identifier {}, could not find corresponding "
511 + "state machine ... exiting", radiusPacket.getIdentifier());
512 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
513 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
514 return;
515 }
516
517 idManager.releaseIdentifier(identifier);
518 StateMachine stateMachine = stateMachines.get(sessionId);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100519 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700520 log.error("Invalid packet identifier {}, could not find corresponding "
521 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000522 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
523 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100524 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700525 }
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000526
527 //instance of StateMachine using the sessionId for updating machine stats
Jonathan Hart612651f2019-11-25 09:21:43 -0800528 StateMachine machineStats = stateMachines.get(stateMachine.sessionId());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000529
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100530 EAP eapPayload;
531 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000532 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000533
534 //increasing packets and octets received from server
535 machineStats.incrementTotalPacketsReceived();
536 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
537
kartikey dubeye1545422019-05-22 12:53:45 +0000538 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
539 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
540 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
541 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100542 switch (radiusPacket.getCode()) {
543 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400544 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100545 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
546 byte[] challengeState = null;
547 if (radiusAttrState != null) {
548 challengeState = radiusAttrState.getValue();
549 }
550 eapPayload = radiusPacket.decapsulateMessage();
551 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
552 eth = buildEapolResponse(stateMachine.supplicantAddress(),
553 MacAddress.valueOf(nasMacAddress),
554 stateMachine.vlanId(),
555 EAPOL.EAPOL_PACKET,
556 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400557 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000558 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000559 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000560 outPacketSupp.add(eapPayload.getIdentifier());
561 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000562 //increasing packets send to server
563 machineStats.incrementTotalPacketsSent();
564 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100565 break;
566 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400567 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100568 //send an EAPOL - Success to the supplicant.
569 byte[] eapMessageSuccess =
570 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700571 eapPayload = EAP.deserializer().deserialize(
572 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100573 eth = buildEapolResponse(stateMachine.supplicantAddress(),
574 MacAddress.valueOf(nasMacAddress),
575 stateMachine.vlanId(),
576 EAPOL.EAPOL_PACKET,
577 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400578 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000579 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
580 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100581
582 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000583 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000584 //increasing packets send to server
585 machineStats.incrementTotalPacketsSent();
586 machineStats.incrementTotalOctetSent(eapPayload.getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100587 break;
588 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400589 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100590 //send an EAPOL - Failure to the supplicant.
591 byte[] eapMessageFailure;
592 eapPayload = new EAP();
593 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
594 if (radiusAttrEap == null) {
595 eapPayload.setCode(EAP.FAILURE);
596 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
597 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
598 } else {
599 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700600 eapPayload = EAP.deserializer().deserialize(
601 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100602 }
603 eth = buildEapolResponse(stateMachine.supplicantAddress(),
604 MacAddress.valueOf(nasMacAddress),
605 stateMachine.vlanId(),
606 EAPOL.EAPOL_PACKET,
607 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400608 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000609 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
610 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
611
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100612 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000613 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000614 //increasing packets send to server
615 machineStats.incrementTotalPacketsSent();
616 machineStats.incrementTotalOctetSent(eapPayload.getLength());
617 //pushing machine stats to kafka
618 AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
619 aaaSupplicantStatsManager.getMachineStatsDelegate()
620 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, machineObj));
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100621 break;
622 default:
623 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000624 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000625 //increasing packets received to server
626 machineStats.incrementTotalPacketsReceived();
627 machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100628 }
kartikey dubeye1545422019-05-22 12:53:45 +0000629 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700630 }
631
Ray Milkey967776a2015-10-07 14:37:17 -0700632 /**
633 * Send the ethernet packet to the supplicant.
634 *
635 * @param ethernetPkt the ethernet packet
636 * @param connectPoint the connect point to send out
637 */
Shubham Sharma1f193582019-07-11 12:12:41 +0000638 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700639 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
640 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
641 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharma1f193582019-07-11 12:12:41 +0000642 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
Saurav Das987441a2018-09-18 16:33:47 -0700643 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700644 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
645 eap, ethernetPkt, connectPoint);
646 }
Ray Milkey967776a2015-10-07 14:37:17 -0700647 packetService.emit(packet);
Shubham Sharma1f193582019-07-11 12:12:41 +0000648 if (isChallengeResponse) {
649 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
650 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000651 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
652 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700653 }
654
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400655 @Override
656 public String toString() {
657 return ToStringBuilder.reflectionToString(this);
658 }
659
Jonathan Hart612651f2019-11-25 09:21:43 -0800660 @Override
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800661 public Iterable<AuthenticationRecord> getAuthenticationRecords() {
662 return authentications.asJavaMap().values();
Jonathan Hart612651f2019-11-25 09:21:43 -0800663 }
664
665 @Override
666 public boolean removeAuthenticationStateByMac(MacAddress mac) {
667
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800668 Optional<Versioned<AuthenticationRecord>> r = authentications.values().stream()
669 .filter(v -> v.value().supplicantAddress().equals(mac))
670 .findFirst();
Jonathan Hart612651f2019-11-25 09:21:43 -0800671
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800672 if (r.isEmpty()) {
673 return false;
Jonathan Hart612651f2019-11-25 09:21:43 -0800674 }
675
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800676 Versioned<AuthenticationRecord> removed =
677 authentications.remove(r.get().value().supplicantConnectPoint());
Jonathan Hart612651f2019-11-25 09:21:43 -0800678
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800679 return removed != null;
Jonathan Hart612651f2019-11-25 09:21:43 -0800680 }
681
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800682 StateMachine getStateMachine(String sessionId) {
Jonathan Hart612651f2019-11-25 09:21:43 -0800683 return stateMachines.get(sessionId);
684 }
685
686 private String sessionId(ConnectPoint cp) {
687 return cp.deviceId().toString() + cp.port().toString();
688 }
689
Ari Saha89831742015-06-26 10:31:48 -0700690 // our handler defined as a private inner class
691
692 /**
693 * Packet processor responsible for forwarding packets along their paths.
694 */
695 private class ReactivePacketProcessor implements PacketProcessor {
696 @Override
697 public void process(PacketContext context) {
698
699 // Extract the original Ethernet frame from the packet information
700 InboundPacket pkt = context.inPacket();
701 Ethernet ethPkt = pkt.parsed();
702 if (ethPkt == null) {
703 return;
704 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100705
Jonathan Hart612651f2019-11-25 09:21:43 -0800706 // identify if incoming packet comes from supplicant (EAP) or RADIUS
707 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
708 case EAPOL:
709 handleSupplicantPacket(context.inPacket());
710 break;
711 default:
712 // any other packets let the specific implementation handle
713 impl.handlePacketFromServer(context);
Ari Saha89831742015-06-26 10:31:48 -0700714 }
715 }
716
Ray Milkey9eb293f2015-09-30 15:09:17 -0700717 /**
718 * Creates and initializes common fields of a RADIUS packet.
719 *
Ray Milkey967776a2015-10-07 14:37:17 -0700720 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700721 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700722 * @return RADIUS packet
723 */
Ray Milkey967776a2015-10-07 14:37:17 -0700724 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700725 RADIUS radiusPayload =
726 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
727 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700728
729 // set Request Authenticator in StateMachine
730 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
731
Ray Milkey9eb293f2015-09-30 15:09:17 -0700732 radiusPayload.setIdentifier(identifier);
733 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700734 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700735
736 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800737 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700738
739 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700740
741 return radiusPayload;
742 }
Ari Saha89831742015-06-26 10:31:48 -0700743
744 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700745 * Handles PAE packets (supplicant).
746 *
747 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700748 */
Jonathan Hart612651f2019-11-25 09:21:43 -0800749 private void handleSupplicantPacket(InboundPacket inPacket) {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700750 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700751 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800752 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700753
Jonathan Harta46dddf2015-06-30 15:31:20 -0700754 DeviceId deviceId = inPacket.receivedFrom().deviceId();
755 PortNumber portNumber = inPacket.receivedFrom().port();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800756 String sessionId = sessionId(inPacket.receivedFrom());
Saurav Das987441a2018-09-18 16:33:47 -0700757 EAPOL eapol = (EAPOL) ethPkt.getPayload();
758 if (log.isTraceEnabled()) {
759 log.trace("Received EAPOL packet {} in enclosing packet {} from "
760 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
761 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100762 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700763
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000764 short pktlen = eapol.getPacketLength();
765 byte[] eapPayLoadBuffer = eapol.serialize();
766 int len = eapPayLoadBuffer.length;
767 if (len != (HEADER_LENGTH + pktlen)) {
768 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
769 return;
770 }
771 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
772 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
773 return;
774 }
775 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
776 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
777 }
Jonathan Hart612651f2019-11-25 09:21:43 -0800778
779 StateMachine stateMachine = stateMachines.computeIfAbsent(sessionId, id -> new StateMachine(id, executor));
780 stateMachine.setEapolTypeVal(eapol.getEapolType());
Saurav Das987441a2018-09-18 16:33:47 -0700781
Ari Saha89831742015-06-26 10:31:48 -0700782 switch (eapol.getEapolType()) {
783 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400784 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700785 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800786 stateMachine.setSupplicantAddress(srcMac);
Jonathan Hart5db44532018-07-12 18:13:54 -0700787 stateMachine.start();
Jonathan Hart612651f2019-11-25 09:21:43 -0800788
Shubham Sharma1f193582019-07-11 12:12:41 +0000789 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700790 //send an EAP Request/Identify to the supplicant
791 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100792 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
793 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
794 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800795 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700796 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100797 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400798
Ray Milkeyf51eba22015-09-25 10:24:23 -0700799 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400800 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharma1f193582019-07-11 12:12:41 +0000801 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000802 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
Ari Saha89831742015-06-26 10:31:48 -0700803
804 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800805 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400806 log.debug("EAP packet: EAPOL_LOGOFF");
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000807 //posting the machine stat data for current supplicant device.
808 if (stateMachine.getSessionTerminateReason() == null ||
809 stateMachine.getSessionTerminateReason().equals("")) {
810 stateMachine.setSessionTerminateReason(
811 StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
812 }
813 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
814 aaaSupplicantStatsManager.getMachineStatsDelegate()
815 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
Ray Milkeyb34b4962016-01-04 10:24:43 -0800816 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
817 stateMachine.logoff();
Shubham Sharma1f193582019-07-11 12:12:41 +0000818 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800819 }
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000820 if (stateMachine.state() == StateMachine.STATE_IDLE) {
821 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
822 }
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800823
824 break;
Ari Saha89831742015-06-26 10:31:48 -0700825 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700826 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700827 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700828 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000829 Byte identifier = new Byte(eapPacket.getIdentifier());
Ari Saha89831742015-06-26 10:31:48 -0700830
Jonathan Hart612651f2019-11-25 09:21:43 -0800831 // get identifier for request and store mapping to session ID
832 RequestIdentifier radiusIdentifier = idManager.getNewIdentifier(sessionId);
833
Ari Saha89831742015-06-26 10:31:48 -0700834 byte dataType = eapPacket.getDataType();
835 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700836
Ray Milkey9eb293f2015-09-30 15:09:17 -0700837 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400838 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharma1e43c562019-06-19 14:18:12 +0000839 //Setting the time of this response from RG, only when its not a re-transmission.
840 if (stateMachine.getLastPacketReceivedTime() == 0) {
841 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
842 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700843 // request id access to RADIUS
844 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700845
Jonathan Hart612651f2019-11-25 09:21:43 -0800846 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100847 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800848 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700849
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100850 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000851 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000852 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700853 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000854 if (stateMachine.state() == StateMachine.STATE_PENDING) {
855 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +0000856 stateMachine.incrementTotalPacketsSent();
857 stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
kartikey dubeye1545422019-05-22 12:53:45 +0000858 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700859 stateMachine.requestAccess();
860 break;
Ari Saha89831742015-06-26 10:31:48 -0700861 case EAP.ATTR_MD5:
Shubham Sharma1e43c562019-06-19 14:18:12 +0000862 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400863 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700864 // verify if the EAP identifier corresponds to the
865 // challenge identifier from the client state
866 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700867 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700868 //send the RADIUS challenge response
Jonathan Hart612651f2019-11-25 09:21:43 -0800869 radiusPayload = getRadiusPayload(stateMachine,
870 radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100871 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700872
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800873 if (stateMachine.challengeState() != null) {
874 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
875 stateMachine.challengeState());
876 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800877 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000878 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
879 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
880 outPacketSupp.remove(identifier);
881 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100882 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000883 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000884 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700885 }
886 break;
887 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400888 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700889 // request id access to RADIUS
Jonathan Hart612651f2019-11-25 09:21:43 -0800890 radiusPayload = getRadiusPayload(stateMachine, radiusIdentifier.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100891 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700892
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800893 if (stateMachine.challengeState() != null) {
894 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
895 stateMachine.challengeState());
896 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700897 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700898
Jonathan Hart092dfb22015-11-16 23:05:21 -0800899 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma3c8c7022019-09-13 10:39:47 +0000900 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
901 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
902 outPacketSupp.remove(identifier);
903 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100904 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharma1e43c562019-06-19 14:18:12 +0000905 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharma1f193582019-07-11 12:12:41 +0000906 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700907
Ray Milkeyf3790b82015-10-21 16:28:08 -0700908 if (stateMachine.state() != StateMachine.STATE_PENDING) {
909 stateMachine.requestAccess();
910 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700911
Ari Saha89831742015-06-26 10:31:48 -0700912 break;
913 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400914 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700915 return;
916 }
917 break;
918 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400919 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700920 }
Shubham Sharma1f193582019-07-11 12:12:41 +0000921 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
922 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700923 }
Ray Milkey967776a2015-10-07 14:37:17 -0700924 }
925
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100926 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700927 * Delegate allowing the StateMachine to notify us of events.
928 */
929 private class InternalStateMachineDelegate implements StateMachineDelegate {
930
931 @Override
932 public void notify(AuthenticationEvent authenticationEvent) {
933 log.info("Auth event {} for {}",
934 authenticationEvent.type(), authenticationEvent.subject());
Jonathan Hart612651f2019-11-25 09:21:43 -0800935
936 if (authenticationEvent.type() == AuthenticationEvent.Type.TIMEOUT) {
937 handleStateMachineTimeout(authenticationEvent.subject());
938 }
939
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800940 AuthenticationRecord record = authenticationEvent.authenticationRecord();
941 if (record == null) {
942 authentications.remove(authenticationEvent.subject());
943 } else {
944 authentications.put(authenticationEvent.subject(), record);
945 }
946
Jonathan Hart5db44532018-07-12 18:13:54 -0700947 post(authenticationEvent);
948 }
949 }
950
Jonathan Hart612651f2019-11-25 09:21:43 -0800951 private void handleStateMachineTimeout(ConnectPoint supplicantConnectPoint) {
952 StateMachine stateMachine = stateMachines.remove(sessionId(supplicantConnectPoint));
953
Andrea Campanellae66466a2020-02-03 14:05:45 +0000954 //pushing captured machine stats to kafka
955 stateMachine.setSessionTerminateReason("Time out");
956 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager
957 .getSupplicantStats(stateMachine);
958 aaaSupplicantStatsManager.getMachineStatsDelegate()
959 .notify(new AaaMachineStatisticsEvent(
960 AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
961
Jonathan Hart612651f2019-11-25 09:21:43 -0800962 if (stateMachine.state() == StateMachine.STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) {
963 aaaStatisticsManager.getAaaStats().increaseTimedOutPackets();
964 }
965
966 StateMachine.deleteStateMachineMapping(stateMachine);
967 }
968
Jonathan Hart5db44532018-07-12 18:13:54 -0700969 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100970 * Configuration Listener, handles change in configuration.
971 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700972 private class InternalConfigListener implements NetworkConfigListener {
973
974 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800975 * Reconfigures the AAA application according to the
976 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700977 *
978 * @param cfg configuration object
979 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800980 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400981 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100982
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700983 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800984 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700985 } else {
986 newCfg = cfg;
987 }
988 if (newCfg.nasIp() != null) {
989 nasIpAddress = newCfg.nasIp();
990 }
991 if (newCfg.radiusIp() != null) {
992 radiusIpAddress = newCfg.radiusIp();
993 }
994 if (newCfg.radiusMac() != null) {
995 radiusMacAddress = newCfg.radiusMac();
996 }
997 if (newCfg.nasMac() != null) {
998 nasMacAddress = newCfg.nasMac();
999 }
1000 if (newCfg.radiusSecret() != null) {
1001 radiusSecret = newCfg.radiusSecret();
1002 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001003
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301004 boolean reconfigureCustomizer = false;
1005 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
1006 customizer = newCfg.radiusPktCustomizer();
1007 configurePacketCustomizer();
1008 reconfigureCustomizer = true;
1009 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001010
Deepa Vaddireddye0e10722017-09-27 05:00:10 +05301011 if (radiusConnectionType == null
1012 || reconfigureCustomizer
1013 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
1014 radiusConnectionType = newCfg.radiusConnectionType();
1015 if (impl != null) {
1016 impl.withdrawIntercepts();
1017 impl.clearLocalState();
1018 }
1019 configureRadiusCommunication();
1020 impl.initializeLocalState(newCfg);
1021 impl.requestIntercepts();
1022 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001023 impl.clearLocalState();
1024 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -07001025 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001026 }
1027
1028 @Override
1029 public void event(NetworkConfigEvent event) {
1030
1031 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
1032 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -08001033 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001034
Jonathan Hart092dfb22015-11-16 23:05:21 -08001035 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001036 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +01001037
Matt Jeanneret2ff1a782018-06-13 15:24:25 -04001038 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -07001039 }
1040 }
1041 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001042
Jonathan Hart9d1ce802020-01-28 10:45:08 -08001043 private class InternalMapEventListener implements MapEventListener<ConnectPoint, AuthenticationRecord> {
1044 @Override
1045 public void event(MapEvent<ConnectPoint, AuthenticationRecord> event) {
1046 if (event.type() == MapEvent.Type.REMOVE) {
1047 // remove local state machine if user has requested remove
1048 StateMachine sm = stateMachines.remove(sessionId(event.key()));
1049 if (sm != null) {
1050 sm.stop();
1051 }
1052 }
1053 }
1054 }
1055
Amit Ghoshf739be52017-09-21 15:49:37 +01001056 private class InternalDeviceListener implements DeviceListener {
1057 @Override
1058 public void event(DeviceEvent event) {
Andrea Campanellabba33672020-02-11 14:03:01 +01001059 DeviceId deviceId = event.subject().id();
Amit Ghoshf739be52017-09-21 15:49:37 +01001060 switch (event.type()) {
1061 case PORT_REMOVED:
Amit Ghoshf739be52017-09-21 15:49:37 +01001062 PortNumber portNumber = event.port().number();
Andrea Campanellabba33672020-02-11 14:03:01 +01001063 String sessionId = deviceId.toString() + portNumber.toString();
Girish Kumar064084c2020-02-04 08:32:46 +00001064 log.debug("Received PORT_REMOVED event. Clearing AAA Session with Id {}", sessionId);
1065 flushStateMachineSession(sessionId,
1066 StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
Kartikey Dubeyadeb26e2019-10-01 12:18:35 +00001067
Girish Kumar064084c2020-02-04 08:32:46 +00001068 break;
Andrea Campanellabba33672020-02-11 14:03:01 +01001069 case DEVICE_AVAILABILITY_CHANGED:
1070 if (!deviceService.isAvailable(deviceId)) {
1071 log.debug("Received DEVICE_AVAILABILITY_CHANGED event for {}, " +
1072 "went available to un-available", deviceId);
1073 clearAllSessionStateForDevice(deviceId);
1074 }
1075 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001076 case DEVICE_REMOVED:
Girish Kumar064084c2020-02-04 08:32:46 +00001077 log.debug("Received DEVICE_REMOVED event for {}", deviceId);
Andrea Campanellabba33672020-02-11 14:03:01 +01001078 clearAllSessionStateForDevice(deviceId);
Amit Ghoshf739be52017-09-21 15:49:37 +01001079 break;
Girish Kumar064084c2020-02-04 08:32:46 +00001080
Amit Ghoshf739be52017-09-21 15:49:37 +01001081 default:
1082 return;
1083 }
1084 }
Girish Kumar064084c2020-02-04 08:32:46 +00001085
Andrea Campanellabba33672020-02-11 14:03:01 +01001086 private void clearAllSessionStateForDevice(DeviceId deviceId) {
1087 Set<String> associatedSessions = Sets.newHashSet();
1088 for (Entry<String, StateMachine> stateMachineEntry : stateMachines.entrySet()) {
1089 ConnectPoint cp = stateMachineEntry.getValue().supplicantConnectpoint();
1090 if (cp != null && cp.deviceId().toString().equals(deviceId.toString())) {
1091 associatedSessions.add(stateMachineEntry.getKey());
1092 }
1093 }
1094
1095 for (String session : associatedSessions) {
1096 log.debug("Clearing AAA Session {} associated with Removed Device", session);
1097 flushStateMachineSession(session,
1098 StateMachine.SessionTerminationReasons.DEVICE_REMOVED.getReason());
1099 }
1100 }
1101
Girish Kumar064084c2020-02-04 08:32:46 +00001102 private void flushStateMachineSession(String sessionId, String terminationReason) {
1103 StateMachine stateMachine = stateMachines.get(sessionId);
1104 if (stateMachine != null) {
1105 stateMachine.setSessionTerminateReason(terminationReason);
1106 }
1107
1108 //pushing captured machine stats to kafka
1109 AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
1110 aaaSupplicantStatsManager.getMachineStatsDelegate()
1111 .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
1112
1113 StateMachine removed = stateMachines.remove(sessionId);
1114 if (removed != null) {
1115 StateMachine.deleteStateMachineMapping(removed);
1116 }
1117 }
Amit Ghoshf739be52017-09-21 15:49:37 +01001118 }
Girish Kumar064084c2020-02-04 08:32:46 +00001119
kartikey dubeye1545422019-05-22 12:53:45 +00001120 private class AuthenticationStatisticsEventPublisher implements Runnable {
1121 private final Logger log = getLogger(getClass());
1122 public void run() {
1123 log.info("Notifying AuthenticationStatisticsEvent");
1124 aaaStatisticsManager.calculatePacketRoundtripTime();
1125 log.debug("AcceptResponsesRx---" + aaaStatisticsManager.getAaaStats().getAcceptResponsesRx());
1126 log.debug("AccessRequestsTx---" + aaaStatisticsManager.getAaaStats().getAccessRequestsTx());
1127 log.debug("ChallengeResponsesRx---" + aaaStatisticsManager.getAaaStats().getChallengeResponsesRx());
1128 log.debug("DroppedResponsesRx---" + aaaStatisticsManager.getAaaStats().getDroppedResponsesRx());
1129 log.debug("InvalidValidatorsRx---" + aaaStatisticsManager.getAaaStats().getInvalidValidatorsRx());
1130 log.debug("MalformedResponsesRx---" + aaaStatisticsManager.getAaaStats().getMalformedResponsesRx());
1131 log.debug("PendingRequests---" + aaaStatisticsManager.getAaaStats().getPendingRequests());
1132 log.debug("RejectResponsesRx---" + aaaStatisticsManager.getAaaStats().getRejectResponsesRx());
1133 log.debug("RequestReTx---" + aaaStatisticsManager.getAaaStats().getRequestReTx());
1134 log.debug("RequestRttMilis---" + aaaStatisticsManager.getAaaStats().getRequestRttMilis());
1135 log.debug("UnknownServerRx---" + aaaStatisticsManager.getAaaStats().getUnknownServerRx());
1136 log.debug("UnknownTypeRx---" + aaaStatisticsManager.getAaaStats().getUnknownTypeRx());
Shubham Sharma1e43c562019-06-19 14:18:12 +00001137 log.debug("TimedOutPackets----" + aaaStatisticsManager.getAaaStats().getTimedOutPackets());
Shubham Sharma1f193582019-07-11 12:12:41 +00001138 log.debug("EapolLogoffRx---" + aaaStatisticsManager.getAaaStats().getEapolLogoffRx());
1139 log.debug("EapolAuthSuccessTrans---" + aaaStatisticsManager.getAaaStats().getEapolAuthSuccessTrans());
1140 log.debug("EapolAuthFailureTrans---" +
1141 aaaStatisticsManager.getAaaStats().getEapolAuthFailureTrans());
1142 log.debug("EapolStartReqTrans---" +
1143 aaaStatisticsManager.getAaaStats().getEapolStartReqTrans());
1144 log.debug("EapolTransRespNotNak---" +
1145 aaaStatisticsManager.getAaaStats().getEapolTransRespNotNak());
1146 log.debug("EapPktTxauthChooseEap---" +
1147 aaaStatisticsManager.getAaaStats().getEapPktTxauthChooseEap());
1148 log.debug("EapolResIdentityMsgTrans---" +
1149 aaaStatisticsManager.getAaaStats().getEapolResIdentityMsgTrans());
Shubham Sharma3c8c7022019-09-13 10:39:47 +00001150 log.debug("EapolFramesTx---" + aaaStatisticsManager.getAaaStats().getEapolFramesTx());
1151 log.debug("AuthStateIdle---" + aaaStatisticsManager.getAaaStats().getAuthStateIdle());
1152 log.debug("RequestIdFramesTx---" + aaaStatisticsManager.getAaaStats().getRequestIdFramesTx());
1153 log.debug("ReqEapFramesTx---" + aaaStatisticsManager.getAaaStats().getReqEapFramesTx());
1154 log.debug("InvalidPktType---" + aaaStatisticsManager.getAaaStats().getInvalidPktType());
1155 log.debug("InvalidBodyLength---" + aaaStatisticsManager.getAaaStats().getInvalidBodyLength());
1156 log.debug("ValidEapolFramesRx---" + aaaStatisticsManager.getAaaStats().getValidEapolFramesRx());
1157 log.debug("PendingResSupp---" + aaaStatisticsManager.getAaaStats().getPendingResSupp());
1158 log.debug("ResIdEapFramesRx---" + aaaStatisticsManager.getAaaStats().getEapolattrIdentity());
kartikey dubeye1545422019-05-22 12:53:45 +00001159 aaaStatisticsManager.getStatsDelegate().
1160 notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
1161 aaaStatisticsManager.getAaaStats()));
1162 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001163 }
1164
1165 private class ServerStatusChecker implements Runnable {
1166 @Override
1167 public void run() {
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001168 log.debug("Notifying RadiusOperationalStatusEvent");
Shubham Sharma4900ce62019-06-19 14:18:50 +00001169 radiusOperationalStatusService.checkServerOperationalStatus();
Matteo Scandolo3498bc02020-01-08 09:54:12 -08001170 log.trace("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
Shubham Sharma4900ce62019-06-19 14:18:50 +00001171 radiusOperationalStatusService.getRadiusOprStDelegate()
1172 .notify(new RadiusOperationalStatusEvent(
1173 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
1174 radiusOperationalStatusService.
1175 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +00001176 }
Shubham Sharma4900ce62019-06-19 14:18:50 +00001177
1178 }
Jonathan Hart612651f2019-11-25 09:21:43 -08001179}