blob: 83d5c420903abf0d4d7dacb3b9960eeacfe5d0e0 [file] [log] [blame]
Ari Saha89831742015-06-26 10:31:48 -07001/*
Brian O'Connor4e33be22017-08-03 22:45:46 -07002 * Copyright 2015-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
18import org.junit.After;
19import org.junit.Before;
20import org.junit.Test;
Jonathan Hart5db44532018-07-12 18:13:54 -070021import org.onlab.junit.TestUtils;
Ray Milkey967776a2015-10-07 14:37:17 -070022import org.onlab.packet.BasePacket;
Ray Milkeyea366452015-09-30 10:56:43 -070023import org.onlab.packet.DeserializationException;
24import org.onlab.packet.EAP;
Ray Milkeyea366452015-09-30 10:56:43 -070025import org.onlab.packet.Ethernet;
Ray Milkeyea366452015-09-30 10:56:43 -070026import org.onlab.packet.IpAddress;
Ray Milkeyea366452015-09-30 10:56:43 -070027import org.onlab.packet.RADIUS;
28import org.onlab.packet.RADIUSAttribute;
Jonathan Hartc41227c2020-01-28 16:56:49 -080029import org.onosproject.cluster.ClusterServiceAdapter;
30import org.onosproject.cluster.LeadershipServiceAdapter;
31import org.onosproject.cluster.NodeId;
Ray Milkeyea366452015-09-30 10:56:43 -070032import org.onosproject.core.CoreServiceAdapter;
Jonathan Hart5db44532018-07-12 18:13:54 -070033import org.onosproject.event.DefaultEventSinkRegistry;
34import org.onosproject.event.Event;
35import org.onosproject.event.EventDeliveryService;
36import org.onosproject.event.EventSink;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070037import org.onosproject.net.config.Config;
38import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010039import org.onosproject.net.packet.InboundPacket;
Jonathan Hartc41227c2020-01-28 16:56:49 -080040import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080041import org.onosproject.store.service.TestStorageService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070042import org.opencord.aaa.AaaConfig;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070043import org.slf4j.Logger;
Ray Milkeyea366452015-09-30 10:56:43 -070044
Jonathan Hart092dfb22015-11-16 23:05:21 -080045import java.net.InetAddress;
46import java.net.UnknownHostException;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070047import java.util.concurrent.atomic.AtomicReference;
Ray Milkeyea366452015-09-30 10:56:43 -070048
Jonathan Hart5db44532018-07-12 18:13:54 -070049import static com.google.common.base.Preconditions.checkState;
Ray Milkeyea366452015-09-30 10:56:43 -070050import static org.hamcrest.Matchers.is;
51import static org.hamcrest.Matchers.notNullValue;
Jonathan Hart612651f2019-11-25 09:21:43 -080052import static org.hamcrest.Matchers.nullValue;
Ray Milkeyea366452015-09-30 10:56:43 -070053import static org.junit.Assert.assertThat;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070054import static org.junit.Assert.fail;
55import static org.onosproject.net.intent.TestTools.assertAfter;
56import static org.slf4j.LoggerFactory.getLogger;
Ari Saha89831742015-06-26 10:31:48 -070057
58/**
59 * Set of tests of the ONOS application component.
60 */
Jonathan Hart092dfb22015-11-16 23:05:21 -080061public class AaaManagerTest extends AaaTestBase {
Ari Saha89831742015-06-26 10:31:48 -070062
Ray Milkey967776a2015-10-07 14:37:17 -070063 static final String BAD_IP_ADDRESS = "198.51.100.0";
Ari Saha89831742015-06-26 10:31:48 -070064
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070065 private final Logger log = getLogger(getClass());
66
Jonathan Hart092dfb22015-11-16 23:05:21 -080067 private AaaManager aaaManager;
kartikey dubeye1545422019-05-22 12:53:45 +000068 private AaaStatisticsManager aaaStatisticsManager;
Ray Milkeyea366452015-09-30 10:56:43 -070069
Jonathan Hart092dfb22015-11-16 23:05:21 -080070 class AaaManagerWithoutRadiusServer extends AaaManager {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010071 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
Ray Milkey967776a2015-10-07 14:37:17 -070072 savePacket(radiusPacket);
73 }
Ray Milkeyea366452015-09-30 10:56:43 -070074 }
Ray Milkeyea366452015-09-30 10:56:43 -070075 /**
Ray Milkey967776a2015-10-07 14:37:17 -070076 * Mocks the AAAConfig class to force usage of an unroutable address for the
77 * RADIUS server.
Ray Milkeyea366452015-09-30 10:56:43 -070078 */
Jonathan Hart092dfb22015-11-16 23:05:21 -080079 static class MockAaaConfig extends AaaConfig {
Ray Milkeyea366452015-09-30 10:56:43 -070080 @Override
Ray Milkey967776a2015-10-07 14:37:17 -070081 public InetAddress radiusIp() {
Ray Milkeyea366452015-09-30 10:56:43 -070082 try {
Ray Milkey967776a2015-10-07 14:37:17 -070083 return InetAddress.getByName(BAD_IP_ADDRESS);
84 } catch (UnknownHostException ex) {
85 // can't happen
86 throw new IllegalStateException(ex);
Ray Milkeyea366452015-09-30 10:56:43 -070087 }
88 }
89 }
90
Jonathan Hartc41227c2020-01-28 16:56:49 -080091 static final class TestLeadershipService extends LeadershipServiceAdapter {
92 @Override
93 public NodeId getLeader(String path) {
94 return new ClusterServiceAdapter().getLocalNode().id();
95 }
96 }
97
Ray Milkeyea366452015-09-30 10:56:43 -070098 /**
Ray Milkeyfcb623d2015-10-01 16:48:18 -070099 * Mocks the network config registry.
100 */
101 @SuppressWarnings("unchecked")
102 private static final class TestNetworkConfigRegistry
103 extends NetworkConfigRegistryAdapter {
104 @Override
105 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800106 AaaConfig aaaConfig = new MockAaaConfig();
Ray Milkey967776a2015-10-07 14:37:17 -0700107 return (C) aaaConfig;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700108 }
109 }
110
Jonathan Hart5db44532018-07-12 18:13:54 -0700111 public static class TestEventDispatcher extends DefaultEventSinkRegistry
112 implements EventDeliveryService {
Jonathan Hart5db44532018-07-12 18:13:54 -0700113 @Override
114 @SuppressWarnings("unchecked")
115 public synchronized void post(Event event) {
116 EventSink sink = getSink(event.getClass());
117 checkState(sink != null, "No sink for event %s", event);
118 sink.process(event);
119 }
120
121 @Override
122 public void setDispatchTimeLimit(long millis) {
123 }
124
125 @Override
126 public long getDispatchTimeLimit() {
127 return 0;
128 }
129 }
130
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700131 /**
Ray Milkeyea366452015-09-30 10:56:43 -0700132 * Sets up the services required by the AAA application.
133 */
Ari Saha89831742015-06-26 10:31:48 -0700134 @Before
135 public void setUp() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800136 aaaManager = new AaaManagerWithoutRadiusServer();
137 aaaManager.netCfgService = new TestNetworkConfigRegistry();
138 aaaManager.coreService = new CoreServiceAdapter();
139 aaaManager.packetService = new MockPacketService();
Amit Ghoshf739be52017-09-21 15:49:37 +0100140 aaaManager.deviceService = new TestDeviceService();
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000141 aaaManager.sadisService = new MockSadisService();
kartikey dubeye1545422019-05-22 12:53:45 +0000142 aaaManager.cfgService = new MockCfgService();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800143 aaaManager.storageService = new TestStorageService();
kartikey dubeye1545422019-05-22 12:53:45 +0000144 aaaStatisticsManager = new AaaStatisticsManager();
Jonathan Hartc41227c2020-01-28 16:56:49 -0800145 aaaStatisticsManager.storageService = new TestStorageService();
146 aaaStatisticsManager.clusterService = new ClusterServiceAdapter();
147 aaaStatisticsManager.leadershipService = new TestLeadershipService();
148 aaaStatisticsManager.clusterCommunicationService = new ClusterCommunicationServiceAdapter();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000149 aaaManager.radiusOperationalStatusService = new RadiusOperationalStatusManager();
kartikey dubeye1545422019-05-22 12:53:45 +0000150 TestUtils.setField(aaaStatisticsManager, "eventDispatcher", new TestEventDispatcher());
Jonathan Hartc41227c2020-01-28 16:56:49 -0800151 aaaStatisticsManager.activate(new MockComponentContext());
kartikey dubeye1545422019-05-22 12:53:45 +0000152 aaaManager.aaaStatisticsManager = this.aaaStatisticsManager;
Jonathan Hart5db44532018-07-12 18:13:54 -0700153 TestUtils.setField(aaaManager, "eventDispatcher", new TestEventDispatcher());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700154
155
kartikey dubeye1545422019-05-22 12:53:45 +0000156 aaaManager.activate(new AaaTestBase.MockComponentContext());
Ari Saha89831742015-06-26 10:31:48 -0700157 }
158
Ray Milkeyea366452015-09-30 10:56:43 -0700159 /**
160 * Tears down the AAA application.
161 */
Ari Saha89831742015-06-26 10:31:48 -0700162 @After
163 public void tearDown() {
kartikey dubeye1545422019-05-22 12:53:45 +0000164 aaaManager.deactivate(new AaaTestBase.MockComponentContext());
Ari Saha89831742015-06-26 10:31:48 -0700165 }
166
Ray Milkeyea366452015-09-30 10:56:43 -0700167 /**
168 * Extracts the RADIUS packet from a packet sent by the supplicant.
169 *
Ray Milkey967776a2015-10-07 14:37:17 -0700170 * @param radius RADIUS packet sent by the supplicant
Ray Milkeyea366452015-09-30 10:56:43 -0700171 * @throws DeserializationException if deserialization of the packet contents
172 * fails.
173 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800174 private void checkRadiusPacketFromSupplicant(RADIUS radius)
Ray Milkeyea366452015-09-30 10:56:43 -0700175 throws DeserializationException {
Ray Milkeyea366452015-09-30 10:56:43 -0700176 assertThat(radius, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700177
Ray Milkey967776a2015-10-07 14:37:17 -0700178 EAP eap = radius.decapsulateMessage();
Ray Milkeyea366452015-09-30 10:56:43 -0700179 assertThat(eap, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700180 }
181
182 /**
183 * Fetches the sent packet at the given index. The requested packet
184 * must be the last packet on the list.
185 *
186 * @param index index into sent packets array
187 * @return packet
188 */
Ray Milkey967776a2015-10-07 14:37:17 -0700189 private BasePacket fetchPacket(int index) {
190 BasePacket packet = savedPackets.get(index);
191 assertThat(packet, notNullValue());
192 return packet;
Ray Milkeyea366452015-09-30 10:56:43 -0700193 }
194
195 /**
196 * Tests the authentication path through the AAA application.
197 *
198 * @throws DeserializationException if packed deserialization fails.
199 */
Ari Saha89831742015-06-26 10:31:48 -0700200 @Test
Jonathan Hart612651f2019-11-25 09:21:43 -0800201 public void testAuthentication() throws Exception {
Ray Milkeyea366452015-09-30 10:56:43 -0700202
203 // (1) Supplicant start up
204
205 Ethernet startPacket = constructSupplicantStartPacket();
206 sendPacket(startPacket);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700207 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200208 Ethernet responsePacket = (Ethernet) fetchPacket(0);
209 checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
210
211 // (2) Supplicant identify
212
213 Ethernet identifyPacket = null;
214 try {
215 identifyPacket = constructSupplicantIdentifyPacket(null,
216 EAP.ATTR_IDENTITY, (byte) 3, null);
217 } catch (Exception e) {
218 log.error(e.getMessage());
219 fail();
220 }
221 sendPacket(identifyPacket);
222 });
223 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
224 RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
225 AtomicReference<Byte> reqId = new AtomicReference<>(radiusIdentifyPacket.getIdentifier());
226
227 try {
228 checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
229 } catch (DeserializationException e) {
230 log.error(e.getMessage());
231 fail();
232 }
233
234 assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
235 assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
236 is("testuser"));
237
238 IpAddress nasIp =
239 IpAddress.valueOf(IpAddress.Version.INET,
240 radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
241 .getValue());
242 assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
243
244 // (3) RADIUS MD5 challenge
245
246 RADIUS radiusCodeAccessChallengePacket =
247 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5,
248 reqId.get(), aaaManager.radiusSecret.getBytes());
249 aaaManager.handleRadiusPacket(radiusCodeAccessChallengePacket);
250 });
251 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
252
253 // State machine should have been created by now
254
255 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
256 assertThat(stateMachine, notNullValue());
257 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
258
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700259 Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
260 checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
Ray Milkeyea366452015-09-30 10:56:43 -0700261
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700262 // (4) Supplicant MD5 response
263 try {
264 Ethernet md5RadiusPacket =
265 constructSupplicantIdentifyPacket(stateMachine,
266 EAP.ATTR_MD5,
267 stateMachine.challengeIdentifier(),
268 radiusChallengeMD5Packet);
269 sendPacket(md5RadiusPacket);
270 } catch (Exception e) {
271 log.error(e.getMessage());
272 fail();
273 }
274 });
Andrea Campanellac4781e62020-10-08 12:58:45 +0200275
276 // State machine should have been created by now
277
278 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
279
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700280 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200281
282
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700283 RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
284 try {
285 checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
286 } catch (Exception e) {
287 log.error(e.getMessage());
288 fail();
289 }
290 //assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 9));
Andrea Campanellac4781e62020-10-08 12:58:45 +0200291 AtomicReference<Byte> reqId = new AtomicReference<>(responseMd5RadiusPacket.getIdentifier());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700292 assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
Ray Milkeyea366452015-09-30 10:56:43 -0700293
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700294 // State machine should be in pending state
Ray Milkey967776a2015-10-07 14:37:17 -0700295
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700296 assertThat(stateMachine, notNullValue());
297 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
Ray Milkey967776a2015-10-07 14:37:17 -0700298
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700299 // (5) RADIUS Success
Ray Milkeyea366452015-09-30 10:56:43 -0700300
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700301 RADIUS successPacket =
302 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT,
303 EAP.SUCCESS, reqId.get(),
304 aaaManager.radiusSecret.getBytes());
305 aaaManager.handleRadiusPacket((successPacket));
306 });
307 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
308 Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
Ray Milkeyea366452015-09-30 10:56:43 -0700309
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700310 checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
Ray Milkeyea366452015-09-30 10:56:43 -0700311
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700312 // State machine should be in authorized state
Ray Milkeyea366452015-09-30 10:56:43 -0700313
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700314 assertThat(stateMachine, notNullValue());
315 assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
316 });
Jonathan Hart612651f2019-11-25 09:21:43 -0800317 }
Ray Milkey967776a2015-10-07 14:37:17 -0700318
Jonathan Hart612651f2019-11-25 09:21:43 -0800319 @Test
320 public void testRemoveAuthentication() {
321 Ethernet startPacket = constructSupplicantStartPacket();
322 sendPacket(startPacket);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200323 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
324 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
Jonathan Hart612651f2019-11-25 09:21:43 -0800325
Andrea Campanellac4781e62020-10-08 12:58:45 +0200326 assertThat(stateMachine, notNullValue());
327 assertThat(stateMachine.state(), is(StateMachine.STATE_STARTED));
Jonathan Hart612651f2019-11-25 09:21:43 -0800328
Andrea Campanellac4781e62020-10-08 12:58:45 +0200329 aaaManager.removeAuthenticationStateByMac(stateMachine.supplicantAddress());
Jonathan Hart612651f2019-11-25 09:21:43 -0800330
Andrea Campanellac4781e62020-10-08 12:58:45 +0200331 assertThat(aaaManager.getStateMachine(SESSION_ID), nullValue());
332 });
Ari Saha89831742015-06-26 10:31:48 -0700333 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700334
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700335 /**
336 * Tests the default configuration.
337 */
338 @Test
339 public void testConfig() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800340 assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
341 assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
342 assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
343 assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700344 }
Ari Saha89831742015-06-26 10:31:48 -0700345}