blob: 8827c1a1af5667936f83b523c86ae587cd904e0e [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
Jonathan Hart092dfb22015-11-16 23:05:21 -080018import com.google.common.base.Charsets;
Ari Saha89831742015-06-26 10:31:48 -070019import org.junit.After;
20import org.junit.Before;
21import org.junit.Test;
Jonathan Hart5db44532018-07-12 18:13:54 -070022import org.onlab.junit.TestUtils;
Ray Milkey967776a2015-10-07 14:37:17 -070023import org.onlab.packet.BasePacket;
Ray Milkeyea366452015-09-30 10:56:43 -070024import org.onlab.packet.DeserializationException;
25import org.onlab.packet.EAP;
Ray Milkeyea366452015-09-30 10:56:43 -070026import org.onlab.packet.Ethernet;
Ray Milkeyea366452015-09-30 10:56:43 -070027import org.onlab.packet.IpAddress;
Ray Milkeyea366452015-09-30 10:56:43 -070028import org.onlab.packet.RADIUS;
29import org.onlab.packet.RADIUSAttribute;
Ray Milkeyea366452015-09-30 10:56:43 -070030import org.onosproject.core.CoreServiceAdapter;
Jonathan Hart5db44532018-07-12 18:13:54 -070031import org.onosproject.event.DefaultEventSinkRegistry;
32import org.onosproject.event.Event;
33import org.onosproject.event.EventDeliveryService;
34import org.onosproject.event.EventSink;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070035import org.onosproject.net.config.Config;
36import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010037import org.onosproject.net.packet.InboundPacket;
Matteo Scandolocf847b82019-04-26 15:00:00 -070038import org.opencord.aaa.AaaConfig;
Ray Milkeyea366452015-09-30 10:56:43 -070039
Jonathan Hart5db44532018-07-12 18:13:54 -070040import java.lang.reflect.Field;
Jonathan Hart092dfb22015-11-16 23:05:21 -080041import java.net.InetAddress;
42import java.net.UnknownHostException;
Ray Milkeyea366452015-09-30 10:56:43 -070043
Jonathan Hart5db44532018-07-12 18:13:54 -070044import static com.google.common.base.Preconditions.checkState;
Ray Milkeyea366452015-09-30 10:56:43 -070045import static org.hamcrest.Matchers.is;
46import static org.hamcrest.Matchers.notNullValue;
47import static org.junit.Assert.assertThat;
Ari Saha89831742015-06-26 10:31:48 -070048
49/**
50 * Set of tests of the ONOS application component.
51 */
Jonathan Hart092dfb22015-11-16 23:05:21 -080052public class AaaManagerTest extends AaaTestBase {
Ari Saha89831742015-06-26 10:31:48 -070053
Ray Milkey967776a2015-10-07 14:37:17 -070054 static final String BAD_IP_ADDRESS = "198.51.100.0";
Ari Saha89831742015-06-26 10:31:48 -070055
Jonathan Hart092dfb22015-11-16 23:05:21 -080056 private AaaManager aaaManager;
Ray Milkeyea366452015-09-30 10:56:43 -070057
Jonathan Hart092dfb22015-11-16 23:05:21 -080058 class AaaManagerWithoutRadiusServer extends AaaManager {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010059 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
Ray Milkey967776a2015-10-07 14:37:17 -070060 savePacket(radiusPacket);
61 }
Ray Milkeyea366452015-09-30 10:56:43 -070062 }
63
64 /**
Ray Milkey967776a2015-10-07 14:37:17 -070065 * Mocks the AAAConfig class to force usage of an unroutable address for the
66 * RADIUS server.
Ray Milkeyea366452015-09-30 10:56:43 -070067 */
Jonathan Hart092dfb22015-11-16 23:05:21 -080068 static class MockAaaConfig extends AaaConfig {
Ray Milkeyea366452015-09-30 10:56:43 -070069 @Override
Ray Milkey967776a2015-10-07 14:37:17 -070070 public InetAddress radiusIp() {
Ray Milkeyea366452015-09-30 10:56:43 -070071 try {
Ray Milkey967776a2015-10-07 14:37:17 -070072 return InetAddress.getByName(BAD_IP_ADDRESS);
73 } catch (UnknownHostException ex) {
74 // can't happen
75 throw new IllegalStateException(ex);
Ray Milkeyea366452015-09-30 10:56:43 -070076 }
77 }
78 }
79
80 /**
Ray Milkeyfcb623d2015-10-01 16:48:18 -070081 * Mocks the network config registry.
82 */
83 @SuppressWarnings("unchecked")
84 private static final class TestNetworkConfigRegistry
85 extends NetworkConfigRegistryAdapter {
86 @Override
87 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
Jonathan Hart092dfb22015-11-16 23:05:21 -080088 AaaConfig aaaConfig = new MockAaaConfig();
Ray Milkey967776a2015-10-07 14:37:17 -070089 return (C) aaaConfig;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070090 }
91 }
92
Jonathan Hart5db44532018-07-12 18:13:54 -070093 public static class TestEventDispatcher extends DefaultEventSinkRegistry
94 implements EventDeliveryService {
95
96 @Override
97 @SuppressWarnings("unchecked")
98 public synchronized void post(Event event) {
99 EventSink sink = getSink(event.getClass());
100 checkState(sink != null, "No sink for event %s", event);
101 sink.process(event);
102 }
103
104 @Override
105 public void setDispatchTimeLimit(long millis) {
106 }
107
108 @Override
109 public long getDispatchTimeLimit() {
110 return 0;
111 }
112 }
113
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700114 /**
Ray Milkeyea366452015-09-30 10:56:43 -0700115 * Constructs an Ethernet packet containing a RADIUS challenge
116 * packet.
117 *
118 * @param challengeCode code to use in challenge packet
119 * @param challengeType type to use in challenge packet
120 * @return Ethernet packet
121 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800122 private RADIUS constructRadiusCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
Ray Milkeyea366452015-09-30 10:56:43 -0700123
Ray Milkey967776a2015-10-07 14:37:17 -0700124 String challenge = "12345678901234567";
Ray Milkeyea366452015-09-30 10:56:43 -0700125
126 EAP eap = new EAP(challengeType, (byte) 1, challengeType,
127 challenge.getBytes(Charsets.US_ASCII));
128 eap.setIdentifier((byte) 1);
129
130 RADIUS radius = new RADIUS();
131 radius.setCode(challengeCode);
132
133 radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
134 challenge.getBytes(Charsets.US_ASCII));
135
136 radius.setPayload(eap);
137 radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
138 eap.serialize());
139
Ray Milkey967776a2015-10-07 14:37:17 -0700140 return radius;
Ray Milkeyea366452015-09-30 10:56:43 -0700141 }
142
Jonathan Hart5db44532018-07-12 18:13:54 -0700143 public static void injectEventDispatcher(Object manager, EventDeliveryService svc) {
144 Class mc = manager.getClass();
145 for (Field f : mc.getSuperclass().getDeclaredFields()) {
146 if (f.getType().equals(EventDeliveryService.class)) {
147 try {
148 TestUtils.setField(manager, f.getName(), svc);
149 } catch (TestUtils.TestUtilsException e) {
150 throw new IllegalArgumentException("Unable to inject reference", e);
151 }
152 break;
153 }
154 }
155 }
156
Ray Milkeyea366452015-09-30 10:56:43 -0700157 /**
158 * Sets up the services required by the AAA application.
159 */
Ari Saha89831742015-06-26 10:31:48 -0700160 @Before
161 public void setUp() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800162 aaaManager = new AaaManagerWithoutRadiusServer();
163 aaaManager.netCfgService = new TestNetworkConfigRegistry();
164 aaaManager.coreService = new CoreServiceAdapter();
165 aaaManager.packetService = new MockPacketService();
Amit Ghoshf739be52017-09-21 15:49:37 +0100166 aaaManager.deviceService = new TestDeviceService();
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000167 aaaManager.sadisService = new MockSadisService();
Jonathan Hart5db44532018-07-12 18:13:54 -0700168 TestUtils.setField(aaaManager, "eventDispatcher", new TestEventDispatcher());
Jonathan Hart092dfb22015-11-16 23:05:21 -0800169 aaaManager.activate();
Ari Saha89831742015-06-26 10:31:48 -0700170 }
171
Ray Milkeyea366452015-09-30 10:56:43 -0700172 /**
173 * Tears down the AAA application.
174 */
Ari Saha89831742015-06-26 10:31:48 -0700175 @After
176 public void tearDown() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800177 aaaManager.deactivate();
Ari Saha89831742015-06-26 10:31:48 -0700178 }
179
Ray Milkeyea366452015-09-30 10:56:43 -0700180 /**
181 * Extracts the RADIUS packet from a packet sent by the supplicant.
182 *
Ray Milkey967776a2015-10-07 14:37:17 -0700183 * @param radius RADIUS packet sent by the supplicant
Ray Milkeyea366452015-09-30 10:56:43 -0700184 * @throws DeserializationException if deserialization of the packet contents
185 * fails.
186 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800187 private void checkRadiusPacketFromSupplicant(RADIUS radius)
Ray Milkeyea366452015-09-30 10:56:43 -0700188 throws DeserializationException {
Ray Milkeyea366452015-09-30 10:56:43 -0700189 assertThat(radius, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700190
Ray Milkey967776a2015-10-07 14:37:17 -0700191 EAP eap = radius.decapsulateMessage();
Ray Milkeyea366452015-09-30 10:56:43 -0700192 assertThat(eap, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700193 }
194
195 /**
196 * Fetches the sent packet at the given index. The requested packet
197 * must be the last packet on the list.
198 *
199 * @param index index into sent packets array
200 * @return packet
201 */
Ray Milkey967776a2015-10-07 14:37:17 -0700202 private BasePacket fetchPacket(int index) {
203 BasePacket packet = savedPackets.get(index);
204 assertThat(packet, notNullValue());
205 return packet;
Ray Milkeyea366452015-09-30 10:56:43 -0700206 }
207
208 /**
209 * Tests the authentication path through the AAA application.
210 *
211 * @throws DeserializationException if packed deserialization fails.
212 */
Ari Saha89831742015-06-26 10:31:48 -0700213 @Test
Ray Milkey967776a2015-10-07 14:37:17 -0700214 public void testAuthentication() throws Exception {
Ray Milkeyea366452015-09-30 10:56:43 -0700215
216 // (1) Supplicant start up
217
218 Ethernet startPacket = constructSupplicantStartPacket();
219 sendPacket(startPacket);
220
Ray Milkey967776a2015-10-07 14:37:17 -0700221 Ethernet responsePacket = (Ethernet) fetchPacket(0);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800222 checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
Ray Milkeyea366452015-09-30 10:56:43 -0700223
224 // (2) Supplicant identify
225
Ray Milkey967776a2015-10-07 14:37:17 -0700226 Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
Ray Milkeyea366452015-09-30 10:56:43 -0700227 sendPacket(identifyPacket);
228
Ray Milkey967776a2015-10-07 14:37:17 -0700229 RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
Ray Milkeyea366452015-09-30 10:56:43 -0700230
Jonathan Hart092dfb22015-11-16 23:05:21 -0800231 checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
Ray Milkey967776a2015-10-07 14:37:17 -0700232
233 assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
234 assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
235 is("testuser"));
Ray Milkeyea366452015-09-30 10:56:43 -0700236
237 IpAddress nasIp =
238 IpAddress.valueOf(IpAddress.Version.INET,
Ray Milkey967776a2015-10-07 14:37:17 -0700239 radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
Ray Milkeyea366452015-09-30 10:56:43 -0700240 .getValue());
Jonathan Hart092dfb22015-11-16 23:05:21 -0800241 assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
Ray Milkeyea366452015-09-30 10:56:43 -0700242
243 // State machine should have been created by now
244
245 StateMachine stateMachine =
Ray Milkey967776a2015-10-07 14:37:17 -0700246 StateMachine.lookupStateMachineBySessionId(SESSION_ID);
Ray Milkeyea366452015-09-30 10:56:43 -0700247 assertThat(stateMachine, notNullValue());
248 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
249
250 // (3) RADIUS MD5 challenge
251
Ray Milkey967776a2015-10-07 14:37:17 -0700252 RADIUS radiusCodeAccessChallengePacket =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800253 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100254 aaaManager.handleRadiusPacket(radiusCodeAccessChallengePacket);
Ray Milkeyea366452015-09-30 10:56:43 -0700255
Ray Milkey967776a2015-10-07 14:37:17 -0700256 Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
Jonathan Hart092dfb22015-11-16 23:05:21 -0800257 checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
Ray Milkeyea366452015-09-30 10:56:43 -0700258
259 // (4) Supplicant MD5 response
260
Ray Milkey967776a2015-10-07 14:37:17 -0700261 Ethernet md5RadiusPacket =
262 constructSupplicantIdentifyPacket(stateMachine,
263 EAP.ATTR_MD5,
264 stateMachine.challengeIdentifier(),
265 radiusChallengeMD5Packet);
Ray Milkeyea366452015-09-30 10:56:43 -0700266 sendPacket(md5RadiusPacket);
Ray Milkey967776a2015-10-07 14:37:17 -0700267
268 RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
269
Jonathan Hart092dfb22015-11-16 23:05:21 -0800270 checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100271 assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 3));
Ray Milkeyea366452015-09-30 10:56:43 -0700272 assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
273
274 // State machine should be in pending state
275
276 assertThat(stateMachine, notNullValue());
277 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
278
Ray Milkey967776a2015-10-07 14:37:17 -0700279 // (5) RADIUS Success
Ray Milkeyea366452015-09-30 10:56:43 -0700280
Ray Milkey967776a2015-10-07 14:37:17 -0700281 RADIUS successPacket =
Jonathan Hart092dfb22015-11-16 23:05:21 -0800282 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS);
Amit Ghoshc9ac1e52017-07-28 12:31:18 +0100283 aaaManager.handleRadiusPacket((successPacket));
Ray Milkey967776a2015-10-07 14:37:17 -0700284 Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
Ray Milkeyea366452015-09-30 10:56:43 -0700285
Jonathan Hart092dfb22015-11-16 23:05:21 -0800286 checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
Ray Milkeyea366452015-09-30 10:56:43 -0700287
288 // State machine should be in authorized state
289
290 assertThat(stateMachine, notNullValue());
291 assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
Ray Milkey967776a2015-10-07 14:37:17 -0700292
Ari Saha89831742015-06-26 10:31:48 -0700293 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700294
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700295 /**
296 * Tests the default configuration.
297 */
298 @Test
299 public void testConfig() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800300 assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
301 assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
302 assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
303 assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700304 }
Ari Saha89831742015-06-26 10:31:48 -0700305}