blob: 8e1f5c1302564bc10c66e1468840173b1558241d [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
Saurav Das987441a2018-09-18 16:33:47 -070018import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.net.InetAddress;
kartikey dubeye1545422019-05-22 12:53:45 +000022import java.net.UnknownHostException;
Saurav Das987441a2018-09-18 16:33:47 -070023import java.nio.ByteBuffer;
24import java.util.Map;
kartikey dubeye1545422019-05-22 12:53:45 +000025import java.util.Dictionary;
26import java.util.HashSet;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000027import java.util.Arrays;
Shubham Sharma47869542019-09-13 10:39:47 +000028import java.util.List;
Saurav Das987441a2018-09-18 16:33:47 -070029
Jonathan Hart932bedc2018-07-12 13:46:09 -070030import org.apache.commons.lang3.builder.ToStringBuilder;
Ari Saha89831742015-06-26 10:31:48 -070031import org.apache.felix.scr.annotations.Component;
32import org.apache.felix.scr.annotations.Deactivate;
kartikey dubeye1545422019-05-22 12:53:45 +000033import org.apache.felix.scr.annotations.Property;
Ari Saha89831742015-06-26 10:31:48 -070034import org.apache.felix.scr.annotations.Reference;
35import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart5db44532018-07-12 18:13:54 -070036import org.apache.felix.scr.annotations.Service;
Jonathan Hart4731dd92018-05-02 17:30:05 -070037import org.onlab.packet.DeserializationException;
Jonathan Harta46dddf2015-06-30 15:31:20 -070038import org.onlab.packet.EAP;
39import org.onlab.packet.EAPOL;
40import org.onlab.packet.EthType;
Ari Saha89831742015-06-26 10:31:48 -070041import org.onlab.packet.Ethernet;
Ari Saha89831742015-06-26 10:31:48 -070042import org.onlab.packet.MacAddress;
Jonathan Harta46dddf2015-06-30 15:31:20 -070043import org.onlab.packet.RADIUS;
44import org.onlab.packet.RADIUSAttribute;
kartikey dubeye1545422019-05-22 12:53:45 +000045import org.onlab.util.Tools;
46import org.onosproject.cfg.ComponentConfigService;
Ari Saha89831742015-06-26 10:31:48 -070047import org.onosproject.core.ApplicationId;
48import org.onosproject.core.CoreService;
Jonathan Hart5db44532018-07-12 18:13:54 -070049import org.onosproject.event.AbstractListenerManager;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010050import org.onosproject.mastership.MastershipService;
Ari Saha89831742015-06-26 10:31:48 -070051import org.onosproject.net.ConnectPoint;
52import org.onosproject.net.DeviceId;
Ari Saha89831742015-06-26 10:31:48 -070053import org.onosproject.net.PortNumber;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070054import org.onosproject.net.config.ConfigFactory;
55import org.onosproject.net.config.NetworkConfigEvent;
56import org.onosproject.net.config.NetworkConfigListener;
57import org.onosproject.net.config.NetworkConfigRegistry;
Amit Ghoshf739be52017-09-21 15:49:37 +010058import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010060import org.onosproject.net.device.DeviceService;
Ari Saha89831742015-06-26 10:31:48 -070061import org.onosproject.net.flow.DefaultTrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070062import org.onosproject.net.flow.TrafficTreatment;
Ari Saha89831742015-06-26 10:31:48 -070063import org.onosproject.net.packet.DefaultOutboundPacket;
64import org.onosproject.net.packet.InboundPacket;
65import org.onosproject.net.packet.OutboundPacket;
66import org.onosproject.net.packet.PacketContext;
Ari Saha89831742015-06-26 10:31:48 -070067import org.onosproject.net.packet.PacketProcessor;
68import org.onosproject.net.packet.PacketService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070069import org.opencord.aaa.AaaConfig;
70import org.opencord.aaa.AuthenticationEvent;
71import org.opencord.aaa.AuthenticationEventListener;
72import org.opencord.aaa.AuthenticationService;
kartikey dubeye1545422019-05-22 12:53:45 +000073import org.opencord.aaa.AuthenticationStatisticsEvent;
74import org.opencord.aaa.AuthenticationStatisticsService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070075import org.opencord.aaa.RadiusCommunicator;
Shubham Sharma048cc262019-06-19 14:18:50 +000076import org.opencord.aaa.RadiusOperationalStatusEvent;
77import org.opencord.aaa.RadiusOperationalStatusService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070078import org.opencord.aaa.StateMachineDelegate;
Shubham Sharma048cc262019-06-19 14:18:50 +000079import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
Gamze Abaka1cfdb192018-10-25 11:39:19 +000080import org.opencord.sadis.BaseInformationService;
81import org.opencord.sadis.SadisService;
82import org.opencord.sadis.SubscriberAndDeviceInformation;
kartikey dubeye1545422019-05-22 12:53:45 +000083import org.osgi.service.component.ComponentContext;
Kartikey Dubeyf72e1952019-06-24 07:09:00 +000084import org.apache.felix.scr.annotations.Modified;
85import org.apache.felix.scr.annotations.Activate;
Ari Saha89831742015-06-26 10:31:48 -070086import org.slf4j.Logger;
kartikey dubeye1545422019-05-22 12:53:45 +000087import com.google.common.base.Strings;
Ari Saha89831742015-06-26 10:31:48 -070088
kartikey dubeye1545422019-05-22 12:53:45 +000089import java.util.concurrent.Executors;
90import java.util.concurrent.ScheduledExecutorService;
91import java.util.concurrent.ScheduledFuture;
92import java.util.concurrent.TimeUnit;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +000093
94import javax.crypto.Mac;
95import javax.crypto.spec.SecretKeySpec;
Ari Saha89831742015-06-26 10:31:48 -070096/**
Jonathan Harta46dddf2015-06-30 15:31:20 -070097 * AAA application for ONOS.
Ari Saha89831742015-06-26 10:31:48 -070098 */
Jonathan Hart5db44532018-07-12 18:13:54 -070099@Service
Ari Saha89831742015-06-26 10:31:48 -0700100@Component(immediate = true)
Jonathan Hart5db44532018-07-12 18:13:54 -0700101public class AaaManager
102 extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
103 implements AuthenticationService {
104
Charles Chandf7ff862017-01-20 11:22:05 -0800105 private static final String APP_NAME = "org.opencord.aaa";
Ray Milkeyf51eba22015-09-25 10:24:23 -0700106
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700107 private final Logger log = getLogger(getClass());
Ray Milkeyf51eba22015-09-25 10:24:23 -0700108
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected CoreService coreService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700111
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected PacketService packetService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700114
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700116 protected NetworkConfigRegistry netCfgService;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700117
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected DeviceService deviceService;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000122 protected SadisService sadisService;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 protected MastershipService mastershipService;
126
kartikey dubeye1545422019-05-22 12:53:45 +0000127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected AuthenticationStatisticsService aaaStatisticsManager;
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000129
kartikey dubeye1545422019-05-22 12:53:45 +0000130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected ComponentConfigService cfgService;
132
Shubham Sharma048cc262019-06-19 14:18:50 +0000133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected RadiusOperationalStatusService radiusOperationalStatusService;
135
kartikey dubeye1545422019-05-22 12:53:45 +0000136 protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
137 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
Amit Ghoshf739be52017-09-21 15:49:37 +0100138 private final DeviceListener deviceListener = new InternalDeviceListener();
139
kartikey dubeye1545422019-05-22 12:53:45 +0000140 private static final int DEFAULT_REPEAT_DELAY = 20;
Shubham Sharma048cc262019-06-19 14:18:50 +0000141 @Property(name = "statisticsGenerationPeriodInSeconds", intValue = DEFAULT_REPEAT_DELAY,
142 label = "AAA Statistics generation frequency in seconds")
143 private int statisticsGenerationPeriodInSeconds = DEFAULT_REPEAT_DELAY;
144
145 private static final int DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION = 30;
146 @Property(name = "operationalStatusEventGenerationPeriodInSeconds",
147 intValue = DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION, label = "AAA Radius Server Operational "
148 + "Status Frequency in seconds")
149 private int operationalStatusEventGenerationPeriodInSeconds = DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION;
150
151 private static final int DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT = 10;
152 @Property(name = "operationalStatusServerTimeoutInSeconds",
153 intValue = DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT, label = "Maximum period(in Seconds) to "
154 + "wait for Status response from AAA Server ")
155 private int operationalStatusServerTimeoutInSeconds = DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT;
156
157 private static final String DEFAULT_STATUS_SERVER_MODE = "AUTO";
158 @Property(name = "operationalStatusEvaluationMode", value = DEFAULT_STATUS_SERVER_MODE,
159 label = "Evaluation mode for determining the Operational Status of Radius Server. Valid values are AUTO "
160 + "(default), STATUS_REQUEST and ACCESS_REQUEST")
161 protected String operationalStatusEvaluationMode = DEFAULT_STATUS_SERVER_MODE;
kartikey dubeye1545422019-05-22 12:53:45 +0000162
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700163 // NAS IP address
164 protected InetAddress nasIpAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100165
166 // self MAC address
Jonathan Hart5db44532018-07-12 18:13:54 -0700167 protected String nasMacAddress;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100168
169 // Parsed RADIUS server addresses
170 protected InetAddress radiusIpAddress;
171
172 // MAC address of RADIUS server or net hop router
173 protected String radiusMacAddress;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700174
175 // RADIUS server secret
176 protected String radiusSecret;
177
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100178 // bindings
179 protected CustomizationInfo customInfo;
Ray Milkey5d99bd12015-10-06 15:41:30 -0700180
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700181 // our application-specific event handler
182 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700183
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700184 // our unique identifier
185 private ApplicationId appId;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700186
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000187 // TimeOut time for cleaning up stateMachines stuck due to pending AAA/EAPOL message.
188 protected int cleanupTimerTimeOutInMins;
189
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100190 // Setup specific customization/attributes on the RADIUS packets
191 PacketCustomizer pktCustomizer;
Ray Milkey967776a2015-10-07 14:37:17 -0700192
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100193 // packet customizer to use
194 private String customizer;
195
196 // Type of connection to use to communicate with Radius server, options are
197 // "socket" or "packet_out"
198 private String radiusConnectionType;
199
Jonathan Hart5db44532018-07-12 18:13:54 -0700200 // Object for the specific type of communication with the RADIUS
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100201 // server, socket based or packet_out based
202 RadiusCommunicator impl = null;
203
204 // latest configuration
205 AaaConfig newCfg;
Ray Milkey967776a2015-10-07 14:37:17 -0700206
kartikey dubeye1545422019-05-22 12:53:45 +0000207 ScheduledFuture<?> scheduledFuture;
Shubham Sharma048cc262019-06-19 14:18:50 +0000208 ScheduledFuture<?> scheduledStatusServerChecker;
kartikey dubeye1545422019-05-22 12:53:45 +0000209 ScheduledExecutorService executor;
210 String configuredAaaServerAddress;
211 HashSet<Byte> outPacketSet = new HashSet<Byte>();
Shubham Sharma47869542019-09-13 10:39:47 +0000212 HashSet<Byte> outPacketSupp = new HashSet<Byte>();
213 static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
214 static final int HEADER_LENGTH = 4;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700215 // Configuration properties factory
216 private final ConfigFactory factory =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800217 new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
218 AaaConfig.class,
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700219 "AAA") {
220 @Override
Jonathan Hart092dfb22015-11-16 23:05:21 -0800221 public AaaConfig createConfig() {
222 return new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700223 }
224 };
Ray Milkeyf51eba22015-09-25 10:24:23 -0700225
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700226 // Listener for config changes
227 private final InternalConfigListener cfgListener = new InternalConfigListener();
Ari Saha89831742015-06-26 10:31:48 -0700228
Jonathan Hart5db44532018-07-12 18:13:54 -0700229 private StateMachineDelegate delegate = new InternalStateMachineDelegate();
230
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700231 /**
232 * Builds an EAPOL packet based on the given parameters.
233 *
234 * @param dstMac destination MAC address
235 * @param srcMac source MAC address
236 * @param vlan vlan identifier
237 * @param eapolType EAPOL type
238 * @param eap EAP payload
239 * @return Ethernet frame
240 */
241 private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100242 short vlan, byte eapolType, EAP eap, byte priorityCode) {
Ari Saha89831742015-06-26 10:31:48 -0700243
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700244 Ethernet eth = new Ethernet();
245 eth.setDestinationMACAddress(dstMac.toBytes());
246 eth.setSourceMACAddress(srcMac.toBytes());
247 eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
248 if (vlan != Ethernet.VLAN_UNTAGGED) {
249 eth.setVlanID(vlan);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100250 eth.setPriorityCode(priorityCode);
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700251 }
252 //eapol header
253 EAPOL eapol = new EAPOL();
254 eapol.setEapolType(eapolType);
255 eapol.setPacketLength(eap.getLength());
Ari Saha89831742015-06-26 10:31:48 -0700256
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700257 //eap part
258 eapol.setPayload(eap);
259
260 eth.setPayload(eapol);
261 eth.setPad(true);
262 return eth;
263 }
Ari Saha89831742015-06-26 10:31:48 -0700264
Ari Saha89831742015-06-26 10:31:48 -0700265 @Activate
kartikey dubeye1545422019-05-22 12:53:45 +0000266 public void activate(ComponentContext context) {
Charles Chandf7ff862017-01-20 11:22:05 -0800267 appId = coreService.registerApplication(APP_NAME);
Jonathan Hart5db44532018-07-12 18:13:54 -0700268 eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400269 netCfgService.addListener(cfgListener);
270 netCfgService.registerConfigFactory(factory);
kartikey dubeye1545422019-05-22 12:53:45 +0000271 cfgService.registerProperties(getClass());
272 modified(context);
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000273 subsService = sadisService.getSubscriberInfoService();
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530274 customInfo = new CustomizationInfo(subsService, deviceService);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800275 cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400276 log.info("Starting with config {} {}", this, newCfg);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530277 configureRadiusCommunication();
Ari Saha89831742015-06-26 10:31:48 -0700278 // register our event handler
Brian O'Connord9c7da02015-07-29 17:49:24 -0700279 packetService.addProcessor(processor, PacketProcessor.director(2));
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700280 StateMachine.initializeMaps();
Jonathan Hart5db44532018-07-12 18:13:54 -0700281 StateMachine.setDelegate(delegate);
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000282 cleanupTimerTimeOutInMins = newCfg.sessionCleanupTimer();
283 StateMachine.setcleanupTimerTimeOutInMins(cleanupTimerTimeOutInMins);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100284 impl.initializeLocalState(newCfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100285 impl.requestIntercepts();
Amit Ghoshf739be52017-09-21 15:49:37 +0100286 deviceService.addListener(deviceListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000287 getConfiguredAaaServerAddress();
Shubham Sharma048cc262019-06-19 14:18:50 +0000288 radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
kartikey dubeye1545422019-05-22 12:53:45 +0000289 authenticationStatisticsPublisher =
290 new AuthenticationStatisticsEventPublisher();
Shubham Sharma048cc262019-06-19 14:18:50 +0000291 executor = Executors.newScheduledThreadPool(3);
292
kartikey dubeye1545422019-05-22 12:53:45 +0000293 scheduledFuture = executor.scheduleAtFixedRate(authenticationStatisticsPublisher,
Shubham Sharma048cc262019-06-19 14:18:50 +0000294 0, statisticsGenerationPeriodInSeconds, TimeUnit.SECONDS);
295 scheduledStatusServerChecker = executor.scheduleAtFixedRate(new ServerStatusChecker(), 0,
296 operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
Amit Ghoshf739be52017-09-21 15:49:37 +0100297
Jian Li13c67162015-12-09 13:20:34 -0800298 log.info("Started");
Ari Saha89831742015-06-26 10:31:48 -0700299 }
300
301 @Deactivate
kartikey dubeye1545422019-05-22 12:53:45 +0000302 public void deactivate(ComponentContext context) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100303 impl.withdrawIntercepts();
Ari Saha89831742015-06-26 10:31:48 -0700304 packetService.removeProcessor(processor);
Deepa Vaddireddyb9c24c62017-09-21 13:45:30 +0530305 netCfgService.removeListener(cfgListener);
kartikey dubeye1545422019-05-22 12:53:45 +0000306 cfgService.unregisterProperties(getClass(), false);
Jonathan Hart5db44532018-07-12 18:13:54 -0700307 StateMachine.unsetDelegate(delegate);
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530308 StateMachine.destroyMaps();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100309 impl.deactivate();
Amit Ghoshf739be52017-09-21 15:49:37 +0100310 deviceService.removeListener(deviceListener);
Jonathan Hart5db44532018-07-12 18:13:54 -0700311 eventDispatcher.removeSink(AuthenticationEvent.class);
kartikey dubeye1545422019-05-22 12:53:45 +0000312 scheduledFuture.cancel(true);
Shubham Sharma048cc262019-06-19 14:18:50 +0000313 scheduledStatusServerChecker.cancel(true);
kartikey dubeye1545422019-05-22 12:53:45 +0000314 executor.shutdown();
Jian Li13c67162015-12-09 13:20:34 -0800315 log.info("Stopped");
Ray Milkey967776a2015-10-07 14:37:17 -0700316 }
kartikey dubeye1545422019-05-22 12:53:45 +0000317 @Modified
318 public void modified(ComponentContext context) {
Shubham Sharma048cc262019-06-19 14:18:50 +0000319 Dictionary<String, Object> properties = context.getProperties();
320 String s = Tools.get(properties, "statisticsGenerationPeriodInSeconds");
321 statisticsGenerationPeriodInSeconds = Strings.isNullOrEmpty(s) ? DEFAULT_REPEAT_DELAY
322 : Integer.parseInt(s.trim());
323
324 s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
325 operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
326 ? DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION
327 : Integer.parseInt(s.trim());
328
329 s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
330 operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT
331 : Integer.parseInt(s.trim());
332
333 s = Tools.get(properties, "operationalStatusEvaluationMode");
334 String newEvaluationModeString = Strings.isNullOrEmpty(s) ? DEFAULT_STATUS_SERVER_MODE : s.trim();
335
336 radiusOperationalStatusService
337 .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
338 RadiusOperationalStatusEvaluationMode newEvaluationMode =
339 RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
340 if (newEvaluationMode != null) {
341 radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
342 operationalStatusEvaluationMode = newEvaluationModeString;
343 } else {
344 properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
345 }
kartikey dubeye1545422019-05-22 12:53:45 +0000346 }
347
Shubham Sharma1ad16632019-11-26 11:09:21 +0000348 protected void configureRadiusCommunication() {
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530349 if (radiusConnectionType.toLowerCase().equals("socket")) {
350 impl = new SocketBasedRadiusCommunicator(appId, packetService, this);
351 } else {
352 impl = new PortBasedRadiusCommunicator(appId, packetService, mastershipService,
353 deviceService, subsService, pktCustomizer, this);
354 }
355 }
356
357 private void configurePacketCustomizer() {
358 switch (customizer.toLowerCase()) {
359 case "sample":
360 pktCustomizer = new SamplePacketCustomizer(customInfo);
361 log.info("Created SamplePacketCustomizer");
362 break;
Saurav Dase72358a2018-11-13 21:56:46 -0800363 case "att":
364 pktCustomizer = new AttPacketCustomizer(customInfo);
365 log.info("Created AttPacketCustomizer");
366 break;
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530367 default:
368 pktCustomizer = new PacketCustomizer(customInfo);
369 log.info("Created default PacketCustomizer");
370 break;
371 }
372 }
373
kartikey dubeye1545422019-05-22 12:53:45 +0000374 private void getConfiguredAaaServerAddress() {
375 try {
376 InetAddress address;
377 if (newCfg.radiusHostName() != null) {
378 address = InetAddress.getByName(newCfg.radiusHostName());
379 } else {
380 address = newCfg.radiusIp();
381 }
382
383 configuredAaaServerAddress = address.getHostAddress();
384 } catch (UnknownHostException uhe) {
385 log.warn("Unable to resolve host {}", newCfg.radiusHostName());
386 }
387 }
388
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000389 private void checkReceivedPacketForValidValidator(RADIUS radiusPacket, byte[] requestAuthenticator) {
390 if (!checkResponseMessageAuthenticator(radiusSecret, radiusPacket, requestAuthenticator)) {
kartikey dubeye1545422019-05-22 12:53:45 +0000391 aaaStatisticsManager.getAaaStats().increaseInvalidValidatorsRx();
392 }
393 }
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000394
395 private boolean checkResponseMessageAuthenticator(String key, RADIUS radiusPacket, byte[] requestAuthenticator) {
396 byte[] newHash = new byte[16];
397 Arrays.fill(newHash, (byte) 0);
398 byte[] messageAuthenticator = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
399 byte[] authenticator = radiusPacket.getAuthenticator();
400 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
401 radiusPacket.setAuthenticator(requestAuthenticator);
402 // Calculate the MD5 HMAC based on the message
403 try {
404 SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
405 Mac mac = Mac.getInstance("HmacMD5");
406 mac.init(keySpec);
407 newHash = mac.doFinal(radiusPacket.serialize());
408 } catch (Exception e) {
409 log.error("Failed to generate message authenticator: {}", e.getMessage());
410 }
411 radiusPacket.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
412 radiusPacket.setAuthenticator(authenticator);
413 // Compare the calculated Message-Authenticator with the one in the message
414 return Arrays.equals(newHash, messageAuthenticator);
415 }
kartikey dubeye1545422019-05-22 12:53:45 +0000416 public void checkForPacketFromUnknownServer(String hostAddress) {
417 if (!hostAddress.equals(configuredAaaServerAddress)) {
Vijaykumar Kushwahafffd3d12019-08-01 11:09:59 +0000418 getConfiguredAaaServerAddress();
419 if (!hostAddress.equals(configuredAaaServerAddress)) {
420 aaaStatisticsManager.getAaaStats().incrementUnknownServerRx();
421 }
kartikey dubeye1545422019-05-22 12:53:45 +0000422 }
423 }
424
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100425 /**
426 * Send RADIUS packet to the RADIUS server.
427 *
428 * @param radiusPacket RADIUS packet to be sent to server.
429 * @param inPkt Incoming EAPOL packet
430 */
431 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
kartikey dubeye1545422019-05-22 12:53:45 +0000432 outPacketSet.add(radiusPacket.getIdentifier());
433 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
434 aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
Shubham Sharma048cc262019-06-19 14:18:50 +0000435 aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100436 impl.sendRadiusPacket(radiusPacket, inPkt);
437 }
Ray Milkey967776a2015-10-07 14:37:17 -0700438
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000439 /**
440 * For scheduling the timer required for cleaning up StateMachine
441 * when no response
442 * from RADIUS SERVER.
443 *
444 * @param sessionId SessionId of the current session
445 * @param stateMachine StateMachine for the id
446 */
447 public void scheduleStateMachineCleanupTimer(String sessionId, StateMachine stateMachine) {
448 StateMachine.CleanupTimerTask cleanupTask = stateMachine.new CleanupTimerTask(sessionId, this);
449 ScheduledFuture<?> cleanupTimer = executor.schedule(cleanupTask, cleanupTimerTimeOutInMins, TimeUnit.MINUTES);
450 stateMachine.setCleanupTimer(cleanupTimer);
451
452 }
453
454 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100455 * Handles RADIUS packets.
456 *
457 * @param radiusPacket RADIUS packet coming from the RADIUS server.
458 * @throws StateMachineException if an illegal state transition is triggered
Jonathan Hart4731dd92018-05-02 17:30:05 -0700459 * @throws DeserializationException if packet deserialization fails
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100460 */
Jonathan Hart4731dd92018-05-02 17:30:05 -0700461 public void handleRadiusPacket(RADIUS radiusPacket)
462 throws StateMachineException, DeserializationException {
Saurav Das987441a2018-09-18 16:33:47 -0700463 if (log.isTraceEnabled()) {
464 log.trace("Received RADIUS packet {}", radiusPacket);
465 }
Shubham Sharma048cc262019-06-19 14:18:50 +0000466 if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
467 radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
468 return;
469 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100470 StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
471 if (stateMachine == null) {
Saurav Das987441a2018-09-18 16:33:47 -0700472 log.error("Invalid packet identifier {}, could not find corresponding "
473 + "state machine ... exiting", radiusPacket.getIdentifier());
kartikey dubeye1545422019-05-22 12:53:45 +0000474 aaaStatisticsManager.getAaaStats().incrementNumberOfSessionsExpired();
475 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100476 return;
Ray Milkey967776a2015-10-07 14:37:17 -0700477 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100478 EAP eapPayload;
479 Ethernet eth;
Vijaykumar Kushwaha056e4cd2019-08-06 13:16:25 +0000480 checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
kartikey dubeye1545422019-05-22 12:53:45 +0000481 if (outPacketSet.contains(radiusPacket.getIdentifier())) {
482 aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
483 outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
484 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100485 switch (radiusPacket.getCode()) {
486 case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400487 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_CHALLENGE");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100488 RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
489 byte[] challengeState = null;
490 if (radiusAttrState != null) {
491 challengeState = radiusAttrState.getValue();
492 }
493 eapPayload = radiusPacket.decapsulateMessage();
494 stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
495 eth = buildEapolResponse(stateMachine.supplicantAddress(),
496 MacAddress.valueOf(nasMacAddress),
497 stateMachine.vlanId(),
498 EAPOL.EAPOL_PACKET,
499 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400500 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000501 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
kartikey dubeye1545422019-05-22 12:53:45 +0000502 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
Shubham Sharma47869542019-09-13 10:39:47 +0000503 outPacketSupp.add(eapPayload.getIdentifier());
504 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100505 break;
506 case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400507 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100508 //send an EAPOL - Success to the supplicant.
509 byte[] eapMessageSuccess =
510 radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700511 eapPayload = EAP.deserializer().deserialize(
512 eapMessageSuccess, 0, eapMessageSuccess.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100513 eth = buildEapolResponse(stateMachine.supplicantAddress(),
514 MacAddress.valueOf(nasMacAddress),
515 stateMachine.vlanId(),
516 EAPOL.EAPOL_PACKET,
517 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400518 log.info("Send EAP success message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000519 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
520 aaaStatisticsManager.getAaaStats().incrementEapolAuthSuccessTrans();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100521
522 stateMachine.authorizeAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000523 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100524 break;
525 case RADIUS.RADIUS_CODE_ACCESS_REJECT:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400526 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100527 //send an EAPOL - Failure to the supplicant.
528 byte[] eapMessageFailure;
529 eapPayload = new EAP();
530 RADIUSAttribute radiusAttrEap = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE);
531 if (radiusAttrEap == null) {
532 eapPayload.setCode(EAP.FAILURE);
533 eapPayload.setIdentifier(stateMachine.challengeIdentifier());
534 eapPayload.setLength(EAP.EAP_HDR_LEN_SUC_FAIL);
535 } else {
536 eapMessageFailure = radiusAttrEap.getValue();
Jonathan Hart4731dd92018-05-02 17:30:05 -0700537 eapPayload = EAP.deserializer().deserialize(
538 eapMessageFailure, 0, eapMessageFailure.length);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100539 }
540 eth = buildEapolResponse(stateMachine.supplicantAddress(),
541 MacAddress.valueOf(nasMacAddress),
542 stateMachine.vlanId(),
543 EAPOL.EAPOL_PACKET,
544 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400545 log.warn("Send EAP failure message to supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000546 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
547 aaaStatisticsManager.getAaaStats().incrementEapolauthFailureTrans();
548
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100549 stateMachine.denyAccess();
kartikey dubeye1545422019-05-22 12:53:45 +0000550 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100551 break;
552 default:
553 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
kartikey dubeye1545422019-05-22 12:53:45 +0000554 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100555 }
kartikey dubeye1545422019-05-22 12:53:45 +0000556 aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
Aaron Kruglikovd39d99e2015-07-03 13:30:57 -0700557 }
558
Ray Milkey967776a2015-10-07 14:37:17 -0700559 /**
560 * Send the ethernet packet to the supplicant.
561 *
562 * @param ethernetPkt the ethernet packet
563 * @param connectPoint the connect point to send out
564 */
Shubham Sharmac155ef82019-07-11 12:12:41 +0000565 private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint, boolean isChallengeResponse) {
Ray Milkey967776a2015-10-07 14:37:17 -0700566 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
567 OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
568 treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
Shubham Sharmac155ef82019-07-11 12:12:41 +0000569 EAPOL eap = ((EAPOL) ethernetPkt.getPayload());
570 EAP eapPkt = (EAP) eap.getPayload();
Saurav Das987441a2018-09-18 16:33:47 -0700571 if (log.isTraceEnabled()) {
Saurav Das987441a2018-09-18 16:33:47 -0700572 log.trace("Sending eapol payload {} enclosed in {} to supplicant at {}",
573 eap, ethernetPkt, connectPoint);
574 }
Ray Milkey967776a2015-10-07 14:37:17 -0700575 packetService.emit(packet);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000576 if (isChallengeResponse) {
577 aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
578 }
Shubham Sharma47869542019-09-13 10:39:47 +0000579 aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
580 aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
Ray Milkey967776a2015-10-07 14:37:17 -0700581 }
582
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400583 @Override
584 public String toString() {
585 return ToStringBuilder.reflectionToString(this);
586 }
587
Ari Saha89831742015-06-26 10:31:48 -0700588 // our handler defined as a private inner class
589
590 /**
591 * Packet processor responsible for forwarding packets along their paths.
592 */
593 private class ReactivePacketProcessor implements PacketProcessor {
594 @Override
595 public void process(PacketContext context) {
596
597 // Extract the original Ethernet frame from the packet information
598 InboundPacket pkt = context.inPacket();
599 Ethernet ethPkt = pkt.parsed();
600 if (ethPkt == null) {
601 return;
602 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100603
Ray Milkeyf51eba22015-09-25 10:24:23 -0700604 try {
605 // identify if incoming packet comes from supplicant (EAP) or RADIUS
606 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
607 case EAPOL:
608 handleSupplicantPacket(context.inPacket());
609 break;
Ray Milkeyf51eba22015-09-25 10:24:23 -0700610 default:
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100611 // any other packets let the specific implementation handle
612 impl.handlePacketFromServer(context);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700613 }
Ray Milkey967776a2015-10-07 14:37:17 -0700614 } catch (StateMachineException e) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100615 log.warn("Unable to process packet:", e);
Ari Saha89831742015-06-26 10:31:48 -0700616 }
617 }
618
Ray Milkey9eb293f2015-09-30 15:09:17 -0700619 /**
620 * Creates and initializes common fields of a RADIUS packet.
621 *
Ray Milkey967776a2015-10-07 14:37:17 -0700622 * @param stateMachine state machine for the request
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700623 * @param eapPacket EAP packet
Ray Milkey9eb293f2015-09-30 15:09:17 -0700624 * @return RADIUS packet
625 */
Ray Milkey967776a2015-10-07 14:37:17 -0700626 private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
Ray Milkey9eb293f2015-09-30 15:09:17 -0700627 RADIUS radiusPayload =
628 new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
629 eapPacket.getIdentifier());
Ray Milkey967776a2015-10-07 14:37:17 -0700630
631 // set Request Authenticator in StateMachine
632 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
633
Ray Milkey9eb293f2015-09-30 15:09:17 -0700634 radiusPayload.setIdentifier(identifier);
635 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
Ray Milkey967776a2015-10-07 14:37:17 -0700636 stateMachine.username());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700637
638 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
Jonathan Hart092dfb22015-11-16 23:05:21 -0800639 AaaManager.this.nasIpAddress.getAddress());
Ray Milkey9eb293f2015-09-30 15:09:17 -0700640
641 radiusPayload.encapsulateMessage(eapPacket);
Ray Milkey9eb293f2015-09-30 15:09:17 -0700642
643 return radiusPayload;
644 }
Ari Saha89831742015-06-26 10:31:48 -0700645
646 /**
Jonathan Harta46dddf2015-06-30 15:31:20 -0700647 * Handles PAE packets (supplicant).
648 *
649 * @param inPacket Ethernet packet coming from the supplicant
Ari Saha89831742015-06-26 10:31:48 -0700650 */
Ray Milkeyf51eba22015-09-25 10:24:23 -0700651 private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
Jonathan Harta46dddf2015-06-30 15:31:20 -0700652 Ethernet ethPkt = inPacket.parsed();
Ari Saha89831742015-06-26 10:31:48 -0700653 // Where does it come from?
Jonathan Hart092dfb22015-11-16 23:05:21 -0800654 MacAddress srcMac = ethPkt.getSourceMAC();
Ari Saha89831742015-06-26 10:31:48 -0700655
Jonathan Harta46dddf2015-06-30 15:31:20 -0700656 DeviceId deviceId = inPacket.receivedFrom().deviceId();
657 PortNumber portNumber = inPacket.receivedFrom().port();
Ari Saha89831742015-06-26 10:31:48 -0700658 String sessionId = deviceId.toString() + portNumber.toString();
Saurav Das987441a2018-09-18 16:33:47 -0700659 EAPOL eapol = (EAPOL) ethPkt.getPayload();
660 if (log.isTraceEnabled()) {
661 log.trace("Received EAPOL packet {} in enclosing packet {} from "
662 + "dev/port: {}/{}", eapol, ethPkt, deviceId,
663 portNumber);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100664 }
Jonathan Harta46dddf2015-06-30 15:31:20 -0700665
Shubham Sharma47869542019-09-13 10:39:47 +0000666 short pktlen = eapol.getPacketLength();
667 byte[] eapPayLoadBuffer = eapol.serialize();
668 int len = eapPayLoadBuffer.length;
669 if (len != (HEADER_LENGTH + pktlen)) {
670 aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
671 return;
672 }
673 if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
674 aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
675 return;
676 }
677 if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
678 aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
679 }
Saurav Das987441a2018-09-18 16:33:47 -0700680 StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
681 if (stateMachine == null) {
682 log.debug("Creating new state machine for sessionId: {} for "
683 + "dev/port: {}/{}", sessionId, deviceId, portNumber);
684 stateMachine = new StateMachine(sessionId);
685 } else {
686 log.debug("Using existing state-machine for sessionId: {}", sessionId);
687 }
688
Ari Saha89831742015-06-26 10:31:48 -0700689 switch (eapol.getEapolType()) {
690 case EAPOL.EAPOL_START:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400691 log.debug("EAP packet: EAPOL_START");
Ray Milkeyf51eba22015-09-25 10:24:23 -0700692 stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000693 if (stateMachine.getCleanupTimer() == null) {
694 scheduleStateMachineCleanupTimer(sessionId, stateMachine);
695 }
Jonathan Hart5db44532018-07-12 18:13:54 -0700696 stateMachine.start();
Shubham Sharmac155ef82019-07-11 12:12:41 +0000697 aaaStatisticsManager.getAaaStats().incrementEapolStartReqTrans();
Ray Milkeyf51eba22015-09-25 10:24:23 -0700698 //send an EAP Request/Identify to the supplicant
699 EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100700 if (ethPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
701 stateMachine.setPriorityCode(ethPkt.getPriorityCode());
702 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800703 Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
Ray Milkeyf51eba22015-09-25 10:24:23 -0700704 ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100705 eapPayload, stateMachine.priorityCode());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400706
Jonathan Hart092dfb22015-11-16 23:05:21 -0800707 stateMachine.setSupplicantAddress(srcMac);
Ray Milkeyf51eba22015-09-25 10:24:23 -0700708 stateMachine.setVlanId(ethPkt.getVlanID());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400709 log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000710 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
Shubham Sharma47869542019-09-13 10:39:47 +0000711 aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
Ari Saha89831742015-06-26 10:31:48 -0700712
713 break;
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800714 case EAPOL.EAPOL_LOGOFF:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400715 log.debug("EAP packet: EAPOL_LOGOFF");
Ray Milkeyb34b4962016-01-04 10:24:43 -0800716 if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
717 stateMachine.logoff();
Shubham Sharmac155ef82019-07-11 12:12:41 +0000718 aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800719 }
Shubham Sharma47869542019-09-13 10:39:47 +0000720 if (stateMachine.state() == StateMachine.STATE_IDLE) {
721 aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
722 }
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800723
724 break;
Ari Saha89831742015-06-26 10:31:48 -0700725 case EAPOL.EAPOL_PACKET:
Ray Milkeyf51eba22015-09-25 10:24:23 -0700726 RADIUS radiusPayload;
Ray Milkey9eb293f2015-09-30 15:09:17 -0700727 // check if this is a Response/Identify or a Response/TLS
Ari Saha89831742015-06-26 10:31:48 -0700728 EAP eapPacket = (EAP) eapol.getPayload();
Shubham Sharma47869542019-09-13 10:39:47 +0000729 Byte identifier = new Byte(eapPacket.getIdentifier());
Ari Saha89831742015-06-26 10:31:48 -0700730
731 byte dataType = eapPacket.getDataType();
732 switch (dataType) {
Ari Saha89831742015-06-26 10:31:48 -0700733
Ray Milkey9eb293f2015-09-30 15:09:17 -0700734 case EAP.ATTR_IDENTITY:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400735 log.debug("EAP packet: EAPOL_PACKET ATTR_IDENTITY");
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000736 //Setting the time of this response from RG, only when its not a re-transmission.
737 if (stateMachine.getLastPacketReceivedTime() == 0) {
738 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
739 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700740 // request id access to RADIUS
741 stateMachine.setUsername(eapPacket.getData());
Ari Saha89831742015-06-26 10:31:48 -0700742
Ray Milkey967776a2015-10-07 14:37:17 -0700743 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100744 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800745 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Ari Saha89831742015-06-26 10:31:48 -0700746
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100747 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000748 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000749 aaaStatisticsManager.getAaaStats().incrementEapolAtrrIdentity();
Ray Milkey9eb293f2015-09-30 15:09:17 -0700750 // change the state to "PENDING"
kartikey dubeye1545422019-05-22 12:53:45 +0000751 if (stateMachine.state() == StateMachine.STATE_PENDING) {
752 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
753 }
Ray Milkey9eb293f2015-09-30 15:09:17 -0700754 stateMachine.requestAccess();
755 break;
Ari Saha89831742015-06-26 10:31:48 -0700756 case EAP.ATTR_MD5:
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000757 stateMachine.setLastPacketReceivedTime(System.currentTimeMillis());
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400758 log.debug("EAP packet: EAPOL_PACKET ATTR_MD5");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700759 // verify if the EAP identifier corresponds to the
760 // challenge identifier from the client state
761 // machine.
Ray Milkeyf61a24e2015-09-24 16:34:02 -0700762 if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
Ari Saha89831742015-06-26 10:31:48 -0700763 //send the RADIUS challenge response
Ray Milkey967776a2015-10-07 14:37:17 -0700764 radiusPayload =
765 getRadiusPayload(stateMachine,
766 stateMachine.identifier(),
767 eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100768 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700769
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800770 if (stateMachine.challengeState() != null) {
771 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
772 stateMachine.challengeState());
773 }
Jonathan Hart092dfb22015-11-16 23:05:21 -0800774 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma47869542019-09-13 10:39:47 +0000775 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
776 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
777 outPacketSupp.remove(identifier);
778 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100779 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000780 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000781 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
Ari Saha89831742015-06-26 10:31:48 -0700782 }
783 break;
784 case EAP.ATTR_TLS:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400785 log.debug("EAP packet: EAPOL_PACKET ATTR_TLS");
Ray Milkey9eb293f2015-09-30 15:09:17 -0700786 // request id access to RADIUS
Ray Milkey967776a2015-10-07 14:37:17 -0700787 radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100788 radiusPayload = pktCustomizer.customizePacket(radiusPayload, inPacket);
Ari Saha89831742015-06-26 10:31:48 -0700789
Qianqian Hub55a1ac2015-12-23 20:44:48 +0800790 if (stateMachine.challengeState() != null) {
791 radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
792 stateMachine.challengeState());
793 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700794 stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
Ari Saha89831742015-06-26 10:31:48 -0700795
Jonathan Hart092dfb22015-11-16 23:05:21 -0800796 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
Shubham Sharma47869542019-09-13 10:39:47 +0000797 if (outPacketSupp.contains(eapPacket.getIdentifier())) {
798 aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
799 outPacketSupp.remove(identifier);
800 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100801 sendRadiusPacket(radiusPayload, inPacket);
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000802 stateMachine.setWaitingForRadiusResponse(true);
Shubham Sharmac155ef82019-07-11 12:12:41 +0000803 aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
Ray Milkey5493b512015-10-21 12:13:49 -0700804
Ray Milkeyf3790b82015-10-21 16:28:08 -0700805 if (stateMachine.state() != StateMachine.STATE_PENDING) {
806 stateMachine.requestAccess();
807 }
Ray Milkeyf51eba22015-09-25 10:24:23 -0700808
Ari Saha89831742015-06-26 10:31:48 -0700809 break;
810 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400811 log.warn("Unknown EAP packet type");
Ari Saha89831742015-06-26 10:31:48 -0700812 return;
813 }
814 break;
815 default:
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400816 log.debug("Skipping EAPOL message {}", eapol.getEapolType());
Ari Saha89831742015-06-26 10:31:48 -0700817 }
Shubham Sharmac155ef82019-07-11 12:12:41 +0000818 aaaStatisticsManager.getAaaStats().countTransRespNotNak();
819 aaaStatisticsManager.getAaaStats().countEapolResIdentityMsgTrans();
Ari Saha89831742015-06-26 10:31:48 -0700820 }
Ray Milkey967776a2015-10-07 14:37:17 -0700821 }
822
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100823 /**
Jonathan Hart5db44532018-07-12 18:13:54 -0700824 * Delegate allowing the StateMachine to notify us of events.
825 */
826 private class InternalStateMachineDelegate implements StateMachineDelegate {
827
828 @Override
829 public void notify(AuthenticationEvent authenticationEvent) {
830 log.info("Auth event {} for {}",
831 authenticationEvent.type(), authenticationEvent.subject());
832 post(authenticationEvent);
833 }
834 }
835
836 /**
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100837 * Configuration Listener, handles change in configuration.
838 */
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700839 private class InternalConfigListener implements NetworkConfigListener {
840
841 /**
Ray Milkeyc9e8dcc2015-12-30 10:31:32 -0800842 * Reconfigures the AAA application according to the
843 * configuration parameters passed.
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700844 *
845 * @param cfg configuration object
846 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800847 private void reconfigureNetwork(AaaConfig cfg) {
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400848 log.info("Reconfiguring AaaConfig from config: {}", cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100849
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700850 if (cfg == null) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800851 newCfg = new AaaConfig();
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700852 } else {
853 newCfg = cfg;
854 }
855 if (newCfg.nasIp() != null) {
856 nasIpAddress = newCfg.nasIp();
857 }
858 if (newCfg.radiusIp() != null) {
859 radiusIpAddress = newCfg.radiusIp();
860 }
861 if (newCfg.radiusMac() != null) {
862 radiusMacAddress = newCfg.radiusMac();
863 }
864 if (newCfg.nasMac() != null) {
865 nasMacAddress = newCfg.nasMac();
866 }
867 if (newCfg.radiusSecret() != null) {
868 radiusSecret = newCfg.radiusSecret();
869 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100870
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530871 boolean reconfigureCustomizer = false;
872 if (customizer == null || !customizer.equals(newCfg.radiusPktCustomizer())) {
873 customizer = newCfg.radiusPktCustomizer();
874 configurePacketCustomizer();
875 reconfigureCustomizer = true;
876 }
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100877
Deepa Vaddireddye0e10722017-09-27 05:00:10 +0530878 if (radiusConnectionType == null
879 || reconfigureCustomizer
880 || !radiusConnectionType.equals(newCfg.radiusConnectionType())) {
881 radiusConnectionType = newCfg.radiusConnectionType();
882 if (impl != null) {
883 impl.withdrawIntercepts();
884 impl.clearLocalState();
885 }
886 configureRadiusCommunication();
887 impl.initializeLocalState(newCfg);
888 impl.requestIntercepts();
889 } else if (impl != null) {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100890 impl.clearLocalState();
891 impl.initializeLocalState(newCfg);
Ray Milkey5d99bd12015-10-06 15:41:30 -0700892 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700893 }
894
895 @Override
896 public void event(NetworkConfigEvent event) {
897
898 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
899 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
Jonathan Hart092dfb22015-11-16 23:05:21 -0800900 event.configClass().equals(AaaConfig.class)) {
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700901
Jonathan Hart092dfb22015-11-16 23:05:21 -0800902 AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700903 reconfigureNetwork(cfg);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100904
Matt Jeanneret2ff1a782018-06-13 15:24:25 -0400905 log.info("Reconfigured: {}", cfg.toString());
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700906 }
907 }
908 }
Amit Ghoshf739be52017-09-21 15:49:37 +0100909
910 private class InternalDeviceListener implements DeviceListener {
911 @Override
912 public void event(DeviceEvent event) {
913
914 switch (event.type()) {
915 case PORT_REMOVED:
916 DeviceId devId = event.subject().id();
917 PortNumber portNumber = event.port().number();
918 String sessionId = devId.toString() + portNumber.toString();
919
920 Map<String, StateMachine> sessionIdMap = StateMachine.sessionIdMap();
921 StateMachine removed = sessionIdMap.remove(sessionId);
922 if (removed != null) {
923 StateMachine.deleteStateMachineMapping(removed);
924 }
925
926 break;
927 default:
928 return;
929 }
930 }
931 }
kartikey dubeye1545422019-05-22 12:53:45 +0000932 private class AuthenticationStatisticsEventPublisher implements Runnable {
933 private final Logger log = getLogger(getClass());
934 public void run() {
935 log.info("Notifying AuthenticationStatisticsEvent");
936 aaaStatisticsManager.calculatePacketRoundtripTime();
937 log.debug("AcceptResponsesRx---" + aaaStatisticsManager.getAaaStats().getAcceptResponsesRx());
938 log.debug("AccessRequestsTx---" + aaaStatisticsManager.getAaaStats().getAccessRequestsTx());
939 log.debug("ChallengeResponsesRx---" + aaaStatisticsManager.getAaaStats().getChallengeResponsesRx());
940 log.debug("DroppedResponsesRx---" + aaaStatisticsManager.getAaaStats().getDroppedResponsesRx());
941 log.debug("InvalidValidatorsRx---" + aaaStatisticsManager.getAaaStats().getInvalidValidatorsRx());
942 log.debug("MalformedResponsesRx---" + aaaStatisticsManager.getAaaStats().getMalformedResponsesRx());
943 log.debug("PendingRequests---" + aaaStatisticsManager.getAaaStats().getPendingRequests());
944 log.debug("RejectResponsesRx---" + aaaStatisticsManager.getAaaStats().getRejectResponsesRx());
945 log.debug("RequestReTx---" + aaaStatisticsManager.getAaaStats().getRequestReTx());
946 log.debug("RequestRttMilis---" + aaaStatisticsManager.getAaaStats().getRequestRttMilis());
947 log.debug("UnknownServerRx---" + aaaStatisticsManager.getAaaStats().getUnknownServerRx());
948 log.debug("UnknownTypeRx---" + aaaStatisticsManager.getAaaStats().getUnknownTypeRx());
Shubham Sharmaa3b1bd32019-06-19 14:18:12 +0000949 log.debug("TimedOutPackets----" + aaaStatisticsManager.getAaaStats().getTimedOutPackets());
Shubham Sharmac155ef82019-07-11 12:12:41 +0000950 log.debug("EapolLogoffRx---" + aaaStatisticsManager.getAaaStats().getEapolLogoffRx());
951 log.debug("EapolAuthSuccessTrans---" + aaaStatisticsManager.getAaaStats().getEapolAuthSuccessTrans());
952 log.debug("EapolAuthFailureTrans---" +
953 aaaStatisticsManager.getAaaStats().getEapolAuthFailureTrans());
954 log.debug("EapolStartReqTrans---" +
955 aaaStatisticsManager.getAaaStats().getEapolStartReqTrans());
956 log.debug("EapolTransRespNotNak---" +
957 aaaStatisticsManager.getAaaStats().getEapolTransRespNotNak());
958 log.debug("EapPktTxauthChooseEap---" +
959 aaaStatisticsManager.getAaaStats().getEapPktTxauthChooseEap());
960 log.debug("EapolResIdentityMsgTrans---" +
961 aaaStatisticsManager.getAaaStats().getEapolResIdentityMsgTrans());
Shubham Sharma47869542019-09-13 10:39:47 +0000962 log.debug("EapolFramesTx---" + aaaStatisticsManager.getAaaStats().getEapolFramesTx());
963 log.debug("AuthStateIdle---" + aaaStatisticsManager.getAaaStats().getAuthStateIdle());
964 log.debug("RequestIdFramesTx---" + aaaStatisticsManager.getAaaStats().getRequestIdFramesTx());
965 log.debug("ReqEapFramesTx---" + aaaStatisticsManager.getAaaStats().getReqEapFramesTx());
966 log.debug("InvalidPktType---" + aaaStatisticsManager.getAaaStats().getInvalidPktType());
967 log.debug("InvalidBodyLength---" + aaaStatisticsManager.getAaaStats().getInvalidBodyLength());
968 log.debug("ValidEapolFramesRx---" + aaaStatisticsManager.getAaaStats().getValidEapolFramesRx());
969 log.debug("PendingResSupp---" + aaaStatisticsManager.getAaaStats().getPendingResSupp());
970 log.debug("ResIdEapFramesRx---" + aaaStatisticsManager.getAaaStats().getEapolattrIdentity());
kartikey dubeye1545422019-05-22 12:53:45 +0000971 aaaStatisticsManager.getStatsDelegate().
972 notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
973 aaaStatisticsManager.getAaaStats()));
974 }
Shubham Sharma048cc262019-06-19 14:18:50 +0000975 }
976
977 private class ServerStatusChecker implements Runnable {
978 @Override
979 public void run() {
980 log.info("Notifying RadiusOperationalStatusEvent");
981 radiusOperationalStatusService.checkServerOperationalStatus();
982 log.info("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
983 radiusOperationalStatusService.getRadiusOprStDelegate()
984 .notify(new RadiusOperationalStatusEvent(
985 RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
986 radiusOperationalStatusService.
987 getRadiusServerOperationalStatus()));
kartikey dubeye1545422019-05-22 12:53:45 +0000988 }
Shubham Sharma048cc262019-06-19 14:18:50 +0000989
990 }
991}