diff options
Diffstat (limited to 'framework/src/onos/apps/aaa')
6 files changed, 571 insertions, 431 deletions
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java index 479ec7ed..72a5b122 100644 --- a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java +++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java @@ -15,10 +15,13 @@ */ package org.onosproject.aaa; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.ByteBuffer; -import java.util.Optional; -import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -30,20 +33,13 @@ import org.onlab.packet.EAP; import org.onlab.packet.EAPOL; import org.onlab.packet.EthType; import org.onlab.packet.Ethernet; -import org.onlab.packet.IPv4; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; import org.onlab.packet.RADIUS; import org.onlab.packet.RADIUSAttribute; -import org.onlab.packet.TpPort; -import org.onlab.packet.UDP; -import org.onlab.packet.VlanId; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DeviceId; -import org.onosproject.net.Host; import org.onosproject.net.PortNumber; import org.onosproject.net.config.ConfigFactory; import org.onosproject.net.config.NetworkConfigEvent; @@ -53,7 +49,6 @@ import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.host.HostService; import org.onosproject.net.packet.DefaultOutboundPacket; import org.onosproject.net.packet.InboundPacket; import org.onosproject.net.packet.OutboundPacket; @@ -63,6 +58,8 @@ import org.onosproject.net.packet.PacketService; import org.onosproject.xosintegration.VoltTenantService; import org.slf4j.Logger; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; import static org.onosproject.net.packet.PacketPriority.CONTROL; import static org.slf4j.LoggerFactory.getLogger; @@ -85,10 +82,6 @@ public class AAA { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected PacketService packetService; - // end host information - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected HostService hostService; - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected VoltTenantService voltTenantService; @@ -121,6 +114,12 @@ public class AAA { // our unique identifier private ApplicationId appId; + // Socket used for UDP communications with RADIUS server + private DatagramSocket radiusSocket; + + // Executor for RADIUS communication thread + private ExecutorService executor; + // Configuration properties factory private final ConfigFactory factory = new ConfigFactory<ApplicationId, AAAConfig>(APP_SUBJECT_FACTORY, @@ -184,7 +183,16 @@ public class AAA { StateMachine.initializeMaps(); - hostService.startMonitoringIp(IpAddress.valueOf(radiusIpAddress)); + try { + radiusSocket = new DatagramSocket(radiusServerPort); + } catch (Exception ex) { + log.error("Can't open RADIUS socket", ex); + } + + executor = Executors.newSingleThreadExecutor( + new ThreadFactoryBuilder() + .setNameFormat("AAA-radius-%d").build()); + executor.execute(radiusListener); } @Deactivate @@ -195,6 +203,24 @@ public class AAA { packetService.removeProcessor(processor); processor = null; StateMachine.destroyMaps(); + radiusSocket.close(); + executor.shutdownNow(); + } + + protected void sendRADIUSPacket(RADIUS radiusPacket) { + + try { + final byte[] data = radiusPacket.serialize(); + final DatagramSocket socket = radiusSocket; + + DatagramPacket packet = + new DatagramPacket(data, data.length, + radiusIpAddress, radiusServerPort); + + socket.send(packet); + } catch (IOException e) { + log.info("Cannot send packet to RADIUS server", e); + } } /** @@ -205,14 +231,6 @@ public class AAA { selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort()); packetService.requestPackets(selector.build(), CONTROL, appId); - - TrafficSelector radSelector = DefaultTrafficSelector.builder() - .matchEthType(EthType.EtherType.IPV4.ethType().toShort()) - .matchIPProtocol(IPv4.PROTOCOL_UDP) - .matchUdpDst(TpPort.tpPort(radiusServerPort)) - .matchUdpSrc(TpPort.tpPort(radiusServerPort)) - .build(); - packetService.requestPackets(radSelector, CONTROL, appId); } /** @@ -222,14 +240,19 @@ public class AAA { TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort()); packetService.cancelPackets(selector.build(), CONTROL, appId); + } - TrafficSelector radSelector = DefaultTrafficSelector.builder() - .matchEthType(EthType.EtherType.IPV4.ethType().toShort()) - .matchIPProtocol(IPv4.PROTOCOL_UDP) - .matchUdpDst(TpPort.tpPort(radiusServerPort)) - .matchUdpSrc(TpPort.tpPort(radiusServerPort)) - .build(); - packetService.cancelPackets(radSelector, CONTROL, appId); + /** + * Send the ethernet packet to the supplicant. + * + * @param ethernetPkt the ethernet packet + * @param connectPoint the connect point to send out + */ + private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) { + TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build(); + OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(), + treatment, ByteBuffer.wrap(ethernetPkt.serialize())); + packetService.emit(packet); } // our handler defined as a private inner class @@ -253,26 +276,11 @@ public class AAA { case EAPOL: handleSupplicantPacket(context.inPacket()); break; - case IPV4: - IPv4 ipv4Packet = (IPv4) ethPkt.getPayload(); - Ip4Address srcIp = Ip4Address.valueOf(ipv4Packet.getSourceAddress()); - Ip4Address radiusIp4Address = Ip4Address.valueOf(radiusIpAddress); - if (srcIp.equals(radiusIp4Address) && ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) { - // TODO: check for port as well when it's configurable - UDP udpPacket = (UDP) ipv4Packet.getPayload(); - - byte[] datagram = udpPacket.getPayload().serialize(); - RADIUS radiusPacket; - radiusPacket = RADIUS.deserializer().deserialize(datagram, 0, datagram.length); - handleRadiusPacket(radiusPacket); - } - - break; default: log.trace("Skipping Ethernet packet type {}", EthType.EtherType.lookup(ethPkt.getEtherType())); } - } catch (DeserializationException | StateMachineException e) { + } catch (StateMachineException e) { log.warn("Unable to process RADIUS packet:", e); } } @@ -280,23 +288,26 @@ public class AAA { /** * Creates and initializes common fields of a RADIUS packet. * - * @param identifier RADIUS identifier + * @param stateMachine state machine for the request * @param eapPacket EAP packet * @return RADIUS packet */ - private RADIUS getRadiusPayload(byte identifier, EAP eapPacket) { + private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) { RADIUS radiusPayload = new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST, eapPacket.getIdentifier()); + + // set Request Authenticator in StateMachine + stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode()); + radiusPayload.setIdentifier(identifier); radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME, - eapPacket.getData()); + stateMachine.username()); radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP, AAA.this.nasIpAddress.getAddress()); radiusPayload.encapsulateMessage(eapPacket); - radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret); return radiusPayload; } @@ -329,13 +340,13 @@ public class AAA { //send an EAP Request/Identify to the supplicant EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null); - Ethernet eth = buildEapolResponse(srcMAC, MacAddress.valueOf(1L), + Ethernet eth = buildEapolResponse(srcMAC, MacAddress.valueOf(nasMacAddress), ethPkt.getVlanID(), EAPOL.EAPOL_PACKET, eapPayload); stateMachine.setSupplicantAddress(srcMAC); stateMachine.setVlanId(ethPkt.getVlanID()); - this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); + sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); break; case EAPOL.EAPOL_PACKET: @@ -350,11 +361,10 @@ public class AAA { // request id access to RADIUS stateMachine.setUsername(eapPacket.getData()); - radiusPayload = getRadiusPayload(stateMachine.identifier(), eapPacket); + radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket); + radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret); - // set Request Authenticator in StateMachine - stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode()); - sendRadiusMessage(radiusPayload); + sendRADIUSPacket(radiusPayload); // change the state to "PENDING" stateMachine.requestAccess(); @@ -365,24 +375,31 @@ public class AAA { // machine. if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) { //send the RADIUS challenge response - radiusPayload = getRadiusPayload(stateMachine.challengeIdentifier(), eapPacket); + radiusPayload = + getRadiusPayload(stateMachine, + stateMachine.identifier(), + eapPacket); radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE, stateMachine.challengeState()); - sendRadiusMessage(radiusPayload); + radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret); + sendRADIUSPacket(radiusPayload); } break; case EAP.ATTR_TLS: // request id access to RADIUS - radiusPayload = getRadiusPayload(stateMachine.identifier(), eapPacket); + radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket); radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE, stateMachine.challengeState()); stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode()); - sendRadiusMessage(radiusPayload); - // TODO: this gets called on every fragment, should only be called at TLS-Start - stateMachine.requestAccess(); + radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret); + sendRADIUSPacket(radiusPayload); + + if (stateMachine.state() != StateMachine.STATE_PENDING) { + stateMachine.requestAccess(); + } break; default: @@ -392,14 +409,18 @@ public class AAA { default: log.trace("Skipping EAPOL message {}", eapol.getEapolType()); } + } + } + + class RadiusListener implements Runnable { /** * Handles RADIUS packets. * * @param radiusPacket RADIUS packet coming from the RADIUS server. */ - private void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException { + protected void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException { StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier()); if (stateMachine == null) { log.error("Invalid session identifier, exiting..."); @@ -410,13 +431,16 @@ public class AAA { Ethernet eth; switch (radiusPacket.getCode()) { case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE: - byte[] challengeState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE).getValue(); + byte[] challengeState = + radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE).getValue(); eapPayload = radiusPacket.decapsulateMessage(); stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState); eth = buildEapolResponse(stateMachine.supplicantAddress(), - MacAddress.valueOf(1L), stateMachine.vlanId(), EAPOL.EAPOL_PACKET, + MacAddress.valueOf(nasMacAddress), + stateMachine.vlanId(), + EAPOL.EAPOL_PACKET, eapPayload); - this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); + sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); break; case RADIUS.RADIUS_CODE_ACCESS_ACCEPT: //send an EAPOL - Success to the supplicant. @@ -425,9 +449,11 @@ public class AAA { eapPayload = new EAP(); eapPayload = (EAP) eapPayload.deserialize(eapMessage, 0, eapMessage.length); eth = buildEapolResponse(stateMachine.supplicantAddress(), - MacAddress.valueOf(1L), stateMachine.vlanId(), EAPOL.EAPOL_PACKET, + MacAddress.valueOf(nasMacAddress), + stateMachine.vlanId(), + EAPOL.EAPOL_PACKET, eapPayload); - this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); + sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint()); stateMachine.authorizeAccess(); break; @@ -439,59 +465,45 @@ public class AAA { } } - private void sendRadiusMessage(RADIUS radiusMessage) { - Set<Host> hosts = hostService.getHostsByIp(IpAddress.valueOf(radiusIpAddress)); - Optional<Host> odst = hosts.stream().filter(h -> h.vlan().toShort() == VlanId.UNTAGGED).findFirst(); - - Host dst; - if (!odst.isPresent()) { - log.info("Radius server {} is not present", radiusIpAddress); - return; - } else { - dst = odst.get(); - } - - UDP udp = new UDP(); - IPv4 ip4Packet = new IPv4(); - Ethernet ethPkt = new Ethernet(); - radiusMessage.setParent(udp); - udp.setDestinationPort(radiusServerPort); - udp.setSourcePort(radiusServerPort); - udp.setPayload(radiusMessage); - udp.setParent(ip4Packet); - ip4Packet.setSourceAddress(AAA.this.nasIpAddress.getHostAddress()); - ip4Packet.setDestinationAddress(AAA.this.radiusIpAddress.getHostAddress()); - ip4Packet.setProtocol(IPv4.PROTOCOL_UDP); - ip4Packet.setPayload(udp); - ip4Packet.setParent(ethPkt); - ethPkt.setDestinationMACAddress(radiusMacAddress); - ethPkt.setSourceMACAddress(nasMacAddress); - ethPkt.setEtherType(Ethernet.TYPE_IPV4); - ethPkt.setPayload(ip4Packet); - - TrafficTreatment treatment = DefaultTrafficTreatment.builder() - .setOutput(PortNumber.portNumber(radiusPort)).build(); - OutboundPacket packet = new DefaultOutboundPacket(DeviceId.deviceId(radiusSwitch), - treatment, ByteBuffer.wrap(ethPkt.serialize())); - packetService.emit(packet); - } + @Override + public void run() { + boolean done = false; + int packetNumber = 1; + + log.info("UDP listener thread starting up"); + RADIUS inboundRadiusPacket; + while (!done) { + try { + byte[] packetBuffer = new byte[RADIUS.RADIUS_MAX_LENGTH]; + DatagramPacket inboundBasePacket = + new DatagramPacket(packetBuffer, packetBuffer.length); + DatagramSocket socket = radiusSocket; + socket.receive(inboundBasePacket); + log.info("Packet #{} received", packetNumber++); + try { + inboundRadiusPacket = + RADIUS.deserializer() + .deserialize(inboundBasePacket.getData(), + 0, + inboundBasePacket.getLength()); + handleRadiusPacket(inboundRadiusPacket); + } catch (DeserializationException dex) { + log.error("Cannot deserialize packet", dex); + } catch (StateMachineException sme) { + log.error("Illegal state machine operation", sme); + } - /** - * Send the ethernet packet to the supplicant. - * - * @param ethernetPkt the ethernet packet - * @param connectPoint the connect point to send out - */ - private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) { - TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build(); - OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(), - treatment, ByteBuffer.wrap(ethernetPkt.serialize())); - packetService.emit(packet); + } catch (IOException e) { + log.info("Socket was closed, exiting listener thread"); + done = true; + } + } } - } + RadiusListener radiusListener = new RadiusListener(); + private class InternalConfigListener implements NetworkConfigListener { /** diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java index c18d2bf2..73be7691 100644 --- a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java +++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java @@ -37,13 +37,13 @@ public class AAAConfig extends Config<ApplicationId> { private static final String RADIUS_PORT = "radiusPort"; // RADIUS server IP address - protected static final String DEFAULT_RADIUS_IP = "192.168.1.10"; + protected static final String DEFAULT_RADIUS_IP = "10.128.10.4"; // RADIUS MAC address protected static final String DEFAULT_RADIUS_MAC = "00:00:00:00:01:10"; // NAS IP address - protected static final String DEFAULT_NAS_IP = "192.168.1.11"; + protected static final String DEFAULT_NAS_IP = "10.128.9.244"; // NAS MAC address protected static final String DEFAULT_NAS_MAC = "00:00:00:00:10:01"; diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java new file mode 100644 index 00000000..fb513ced --- /dev/null +++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java @@ -0,0 +1,151 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.aaa; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onlab.packet.EAP; +import org.onlab.packet.EAPOL; +import org.onlab.packet.Ethernet; +import org.onosproject.core.CoreServiceAdapter; +import org.onosproject.net.config.Config; +import org.onosproject.net.config.NetworkConfigRegistryAdapter; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +/** + * Set of tests of the ONOS application component. These use an existing RADIUS + * server and sends live packets over the network to it. + */ +@Ignore ("This should not be run as part of the standard build") +public class AAAIntegrationTest extends AAATestBase { + + private AAA aaa; + + /** + * Mocks the network config registry. + */ + @SuppressWarnings("unchecked") + static final class TestNetworkConfigRegistry + extends NetworkConfigRegistryAdapter { + @Override + public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) { + return (C) new AAAConfig(); + } + } + + /** + * Sets up the services required by the AAA application. + */ + @Before + public void setUp() { + aaa = new AAA(); + aaa.netCfgService = new TestNetworkConfigRegistry(); + aaa.coreService = new CoreServiceAdapter(); + aaa.packetService = new MockPacketService(); + aaa.activate(); + } + + /** + * Fetches the sent packet at the given index. The requested packet + * must be the last packet on the list. + * + * @param index index into sent packets array + * @return packet + */ + private Ethernet fetchPacket(int index) { + for (int iteration = 0; iteration < 20; iteration++) { + if (savedPackets.size() > index) { + return (Ethernet) savedPackets.get(index); + } else { + try { + Thread.sleep(250); + } catch (Exception ex) { + return null; + } + } + } + return null; + } + + /** + * Tests the authentication path through the AAA application by sending + * packets to the RADIUS server and checking the state machine + * transitions. + * + * @throws Exception when an unhandled error occurs + */ + @Test + public void testAuthentication() throws Exception { + + // (1) Supplicant start up + + Ethernet startPacket = constructSupplicantStartPacket(); + sendPacket(startPacket); + + Ethernet responsePacket = fetchPacket(0); + assertThat(responsePacket, notNullValue()); + checkRadiusPacket(aaa, responsePacket, EAP.REQUEST); + + // (2) Supplicant identify + + Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null); + sendPacket(identifyPacket); + + // State machine should have been created by now + + StateMachine stateMachine = + StateMachine.lookupStateMachineBySessionId(SESSION_ID); + assertThat(stateMachine, notNullValue()); + assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING)); + + // (3) RADIUS MD5 challenge + + Ethernet radiusChallengeMD5Packet = fetchPacket(1); + assertThat(radiusChallengeMD5Packet, notNullValue()); + checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.REQUEST); + + + // (4) Supplicant MD5 response + + Ethernet md5RadiusPacket = + constructSupplicantIdentifyPacket(stateMachine, + EAP.ATTR_MD5, + stateMachine.challengeIdentifier(), + radiusChallengeMD5Packet); + sendPacket(md5RadiusPacket); + + + // (5) RADIUS Success + + Ethernet successRadiusPacket = fetchPacket(2); + assertThat(successRadiusPacket, notNullValue()); + EAPOL successEAPOL = (EAPOL) successRadiusPacket.getPayload(); + EAP successEAP = (EAP) successEAPOL.getPayload(); + assertThat(successEAP.getCode(), is(EAP.SUCCESS)); + + // State machine should be in authorized state + + assertThat(stateMachine, notNullValue()); + assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED)); + + } + +} + diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java index 75a60336..860a7dbd 100644 --- a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java +++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java @@ -15,164 +15,61 @@ */ package org.onosproject.aaa; -import java.nio.ByteBuffer; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.net.InetAddress; +import java.net.UnknownHostException; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.onlab.packet.Data; +import org.onlab.packet.BasePacket; import org.onlab.packet.DeserializationException; import org.onlab.packet.EAP; -import org.onlab.packet.EAPOL; -import org.onlab.packet.EthType; import org.onlab.packet.Ethernet; -import org.onlab.packet.IPv4; import org.onlab.packet.IpAddress; -import org.onlab.packet.MacAddress; import org.onlab.packet.RADIUS; import org.onlab.packet.RADIUSAttribute; -import org.onlab.packet.UDP; -import org.onlab.packet.VlanId; import org.onosproject.core.CoreServiceAdapter; -import org.onosproject.net.Annotations; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; import org.onosproject.net.config.Config; import org.onosproject.net.config.NetworkConfigRegistryAdapter; -import org.onosproject.net.host.HostServiceAdapter; -import org.onosproject.net.packet.DefaultInboundPacket; -import org.onosproject.net.packet.DefaultPacketContext; -import org.onosproject.net.packet.InboundPacket; -import org.onosproject.net.packet.OutboundPacket; -import org.onosproject.net.packet.PacketContext; -import org.onosproject.net.packet.PacketProcessor; -import org.onosproject.net.packet.PacketServiceAdapter; -import org.onosproject.net.provider.ProviderId; import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableSet; -import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.onosproject.net.NetTestTools.connectPoint; /** * Set of tests of the ONOS application component. */ -public class AAATest { +public class AAATest extends AAATestBase { - MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a"); - MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a"); + static final String BAD_IP_ADDRESS = "198.51.100.0"; - PacketProcessor packetProcessor; private AAA aaa; - List<Ethernet> savedPackets = new LinkedList<>(); - /** - * Saves the given packet onto the saved packets list. - * - * @param eth packet to save - */ - private void savePacket(Ethernet eth) { - savedPackets.add(eth); + class AAAWithoutRadiusServer extends AAA { + protected void sendRADIUSPacket(RADIUS radiusPacket) { + savePacket(radiusPacket); + } } /** - * Keeps a reference to the PacketProcessor and saves the OutboundPackets. + * Mocks the AAAConfig class to force usage of an unroutable address for the + * RADIUS server. */ - private class MockPacketService extends PacketServiceAdapter { - - @Override - public void addProcessor(PacketProcessor processor, int priority) { - packetProcessor = processor; - } - + static class MockAAAConfig extends AAAConfig { @Override - public void emit(OutboundPacket packet) { + public InetAddress radiusIp() { try { - Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(), - 0, packet.data().array().length); - savePacket(eth); - } catch (Exception e) { - fail(e.getMessage()); + return InetAddress.getByName(BAD_IP_ADDRESS); + } catch (UnknownHostException ex) { + // can't happen + throw new IllegalStateException(ex); } } } /** - * Mocks the DefaultPacketContext. - */ - private final class TestPacketContext extends DefaultPacketContext { - - private TestPacketContext(long time, InboundPacket inPkt, - OutboundPacket outPkt, boolean block) { - super(time, inPkt, outPkt, block); - } - - @Override - public void send() { - // We don't send anything out. - } - } - - /** - * Mocks a host to allow locating the Radius server. - */ - private static final class MockHost implements Host { - @Override - public HostId id() { - return null; - } - - @Override - public MacAddress mac() { - return null; - } - - @Override - public VlanId vlan() { - return VlanId.vlanId(VlanId.UNTAGGED); - } - - @Override - public Set<IpAddress> ipAddresses() { - return null; - } - - @Override - public HostLocation location() { - return null; - } - - @Override - public Annotations annotations() { - return null; - } - - @Override - public ProviderId providerId() { - return null; - } - } - - /** - * Mocks the Host service. - */ - private static final class MockHostService extends HostServiceAdapter { - @Override - public Set<Host> getHostsByIp(IpAddress ip) { - return ImmutableSet.of(new MockHost()); - } - } - - /** * Mocks the network config registry. */ @SuppressWarnings("unchecked") @@ -180,83 +77,12 @@ public class AAATest { extends NetworkConfigRegistryAdapter { @Override public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) { - return (C) new AAAConfig(); + AAAConfig aaaConfig = new MockAAAConfig(); + return (C) aaaConfig; } } /** - * Sends an Ethernet packet to the process method of the Packet Processor. - * - * @param reply Ethernet packet - */ - private void sendPacket(Ethernet reply) { - final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize()); - InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1), - reply, - byteBuffer); - - PacketContext context = new TestPacketContext(127L, inPacket, null, false); - packetProcessor.process(context); - } - - /** - * Constructs an Ethernet packet containing a EAPOL_START Payload. - * - * @return Ethernet packet - */ - private Ethernet constructSupplicantStartPacket() { - Ethernet eth = new Ethernet(); - eth.setDestinationMACAddress(clientMac.toBytes()); - eth.setSourceMACAddress(serverMac.toBytes()); - eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort()); - eth.setVlanID((short) 2); - - EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 1, EAPOL.EAPOL_START, null); - - //eapol header - EAPOL eapol = new EAPOL(); - eapol.setEapolType(EAPOL.EAPOL_START); - eapol.setPacketLength(eap.getLength()); - - //eap part - eapol.setPayload(eap); - - eth.setPayload(eapol); - eth.setPad(true); - return eth; - } - - /** - * Constructs an Ethernet packet containing identification payload. - * - * @return Ethernet packet - */ - private Ethernet constructSupplicantIdentifyPacket(byte type) { - Ethernet eth = new Ethernet(); - eth.setDestinationMACAddress(clientMac.toBytes()); - eth.setSourceMACAddress(serverMac.toBytes()); - eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort()); - eth.setVlanID((short) 2); - - String username = "user"; - EAP eap = new EAP(EAP.REQUEST, (byte) 1, type, - username.getBytes(Charsets.US_ASCII)); - eap.setIdentifier((byte) 1); - - // eapol header - EAPOL eapol = new EAPOL(); - eapol.setEapolType(EAPOL.EAPOL_PACKET); - eapol.setPacketLength(eap.getLength()); - - // eap part - eapol.setPayload(eap); - - eth.setPayload(eapol); - eth.setPad(true); - return eth; - } - - /** * Constructs an Ethernet packet containing a RADIUS challenge * packet. * @@ -264,18 +90,9 @@ public class AAATest { * @param challengeType type to use in challenge packet * @return Ethernet packet */ - private Ethernet constructRADIUSCodeAccessChallengePacket(byte challengeCode, byte challengeType) { - Ethernet eth = new Ethernet(); - eth.setDestinationMACAddress(clientMac.toBytes()); - eth.setSourceMACAddress(serverMac.toBytes()); - eth.setEtherType(EthType.EtherType.IPV4.ethType().toShort()); - eth.setVlanID((short) 2); - - IPv4 ipv4 = new IPv4(); - ipv4.setProtocol(IPv4.PROTOCOL_UDP); - ipv4.setSourceAddress(aaa.radiusIpAddress.getHostAddress()); + private RADIUS constructRADIUSCodeAccessChallengePacket(byte challengeCode, byte challengeType) { - String challenge = "1234"; + String challenge = "12345678901234567"; EAP eap = new EAP(challengeType, (byte) 1, challengeType, challenge.getBytes(Charsets.US_ASCII)); @@ -291,13 +108,7 @@ public class AAATest { radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE, eap.serialize()); - UDP udp = new UDP(); - udp.setPayload(radius); - ipv4.setPayload(udp); - - eth.setPayload(ipv4); - eth.setPad(true); - return eth; + return radius; } /** @@ -305,11 +116,10 @@ public class AAATest { */ @Before public void setUp() { - aaa = new AAA(); + aaa = new AAAWithoutRadiusServer(); aaa.netCfgService = new TestNetworkConfigRegistry(); aaa.coreService = new CoreServiceAdapter(); aaa.packetService = new MockPacketService(); - aaa.hostService = new MockHostService(); aaa.activate(); } @@ -324,60 +134,16 @@ public class AAATest { /** * Extracts the RADIUS packet from a packet sent by the supplicant. * - * @param supplicantPacket packet sent by the supplicant - * @return RADIUS packet + * @param radius RADIUS packet sent by the supplicant * @throws DeserializationException if deserialization of the packet contents * fails. */ - private RADIUS checkAndFetchRADIUSPacketFromSupplicant(Ethernet supplicantPacket) + private void checkRADIUSPacketFromSupplicant(RADIUS radius) throws DeserializationException { - assertThat(supplicantPacket, notNullValue()); - assertThat(supplicantPacket.getVlanID(), is(VlanId.UNTAGGED)); - assertThat(supplicantPacket.getSourceMAC().toString(), is(aaa.nasMacAddress)); - assertThat(supplicantPacket.getDestinationMAC().toString(), is(aaa.radiusMacAddress)); - - assertThat(supplicantPacket.getPayload(), instanceOf(IPv4.class)); - IPv4 ipv4 = (IPv4) supplicantPacket.getPayload(); - assertThat(ipv4, notNullValue()); - assertThat(IpAddress.valueOf(ipv4.getSourceAddress()).toString(), - is(aaa.nasIpAddress.getHostAddress())); - assertThat(IpAddress.valueOf(ipv4.getDestinationAddress()).toString(), - is(aaa.radiusIpAddress.getHostAddress())); - - assertThat(ipv4.getPayload(), instanceOf(UDP.class)); - UDP udp = (UDP) ipv4.getPayload(); - assertThat(udp, notNullValue()); - - assertThat(udp.getPayload(), instanceOf(Data.class)); - Data data = (Data) udp.getPayload(); - RADIUS radius = RADIUS.deserializer() - .deserialize(data.getData(), 0, data.getData().length); assertThat(radius, notNullValue()); - return radius; - } - - /** - * Checks the contents of a RADIUS packet being sent to the RADIUS server. - * - * @param radiusPacket packet to check - * @param code expected code - */ - private void checkRadiusPacket(Ethernet radiusPacket, byte code) { - assertThat(radiusPacket.getVlanID(), is((short) 2)); - - // TODO: These address values seem wrong, but are produced by the current AAA implementation - assertThat(radiusPacket.getSourceMAC(), is(MacAddress.valueOf(1L))); - assertThat(radiusPacket.getDestinationMAC(), is(serverMac)); - assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class)); - EAPOL eapol = (EAPOL) radiusPacket.getPayload(); - assertThat(eapol, notNullValue()); - - assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET)); - assertThat(eapol.getPayload(), instanceOf(EAP.class)); - EAP eap = (EAP) eapol.getPayload(); + EAP eap = radius.decapsulateMessage(); assertThat(eap, notNullValue()); - assertThat(eap.getCode(), is(code)); } /** @@ -387,11 +153,10 @@ public class AAATest { * @param index index into sent packets array * @return packet */ - private Ethernet fetchPacket(int index) { - assertThat(savedPackets.size(), is(index + 1)); - Ethernet eth = savedPackets.get(index); - assertThat(eth, notNullValue()); - return eth; + private BasePacket fetchPacket(int index) { + BasePacket packet = savedPackets.get(index); + assertThat(packet, notNullValue()); + return packet; } /** @@ -400,61 +165,64 @@ public class AAATest { * @throws DeserializationException if packed deserialization fails. */ @Test - public void testAuthentication() throws DeserializationException { - - // Our session id will be the device ID ("of:1") with the port ("1") concatenated - String sessionId = "of:11"; + public void testAuthentication() throws Exception { // (1) Supplicant start up Ethernet startPacket = constructSupplicantStartPacket(); sendPacket(startPacket); - Ethernet responsePacket = fetchPacket(0); - checkRadiusPacket(responsePacket, EAP.ATTR_IDENTITY); + Ethernet responsePacket = (Ethernet) fetchPacket(0); + checkRadiusPacket(aaa, responsePacket, EAP.ATTR_IDENTITY); // (2) Supplicant identify - Ethernet identifyPacket = constructSupplicantIdentifyPacket(EAP.ATTR_IDENTITY); + Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null); sendPacket(identifyPacket); - Ethernet radiusIdentifyPacket = fetchPacket(1); + RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1); + + checkRADIUSPacketFromSupplicant(radiusIdentifyPacket); - RADIUS radiusAccessRequest = checkAndFetchRADIUSPacketFromSupplicant(radiusIdentifyPacket); - assertThat(radiusAccessRequest, notNullValue()); - assertThat(radiusAccessRequest.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST)); - assertThat(new String(radiusAccessRequest.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()), - is("user")); + assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST)); + assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()), + is("testuser")); IpAddress nasIp = IpAddress.valueOf(IpAddress.Version.INET, - radiusAccessRequest.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP) + radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP) .getValue()); assertThat(nasIp.toString(), is(aaa.nasIpAddress.getHostAddress())); // State machine should have been created by now StateMachine stateMachine = - StateMachine.lookupStateMachineBySessionId(sessionId); + StateMachine.lookupStateMachineBySessionId(SESSION_ID); assertThat(stateMachine, notNullValue()); assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING)); // (3) RADIUS MD5 challenge - Ethernet radiusCodeAccessChallengePacket = + RADIUS radiusCodeAccessChallengePacket = constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5); - sendPacket(radiusCodeAccessChallengePacket); + aaa.radiusListener.handleRadiusPacket(radiusCodeAccessChallengePacket); - Ethernet radiusChallengeMD5Packet = fetchPacket(2); - checkRadiusPacket(radiusChallengeMD5Packet, EAP.ATTR_MD5); + Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2); + checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.ATTR_MD5); // (4) Supplicant MD5 response - Ethernet md5RadiusPacket = constructSupplicantIdentifyPacket(EAP.ATTR_MD5); + Ethernet md5RadiusPacket = + constructSupplicantIdentifyPacket(stateMachine, + EAP.ATTR_MD5, + stateMachine.challengeIdentifier(), + radiusChallengeMD5Packet); sendPacket(md5RadiusPacket); - Ethernet supplicantMD5ResponsePacket = fetchPacket(3); - RADIUS responseMd5RadiusPacket = checkAndFetchRADIUSPacketFromSupplicant(supplicantMD5ResponsePacket); - assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 1)); + + RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3); + + checkRADIUSPacketFromSupplicant(responseMd5RadiusPacket); + assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 0)); assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST)); // State machine should be in pending state @@ -462,37 +230,20 @@ public class AAATest { assertThat(stateMachine, notNullValue()); assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING)); - // (5) RADIUS TLS Challenge - - Ethernet radiusCodeAccessChallengeTLSPacket = - constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_TLS); - sendPacket(radiusCodeAccessChallengeTLSPacket); + // (5) RADIUS Success - Ethernet radiusChallengeTLSPacket = fetchPacket(4); - checkRadiusPacket(radiusChallengeTLSPacket, EAP.ATTR_TLS); - - // (6) Supplicant TLS response - - Ethernet tlsRadiusPacket = constructSupplicantIdentifyPacket(EAP.ATTR_TLS); - sendPacket(tlsRadiusPacket); - Ethernet supplicantTLSResponsePacket = fetchPacket(5); - RADIUS responseTLSRadiusPacket = checkAndFetchRADIUSPacketFromSupplicant(supplicantTLSResponsePacket); - assertThat(responseTLSRadiusPacket.getIdentifier(), is((byte) 0)); - assertThat(responseTLSRadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST)); - - // (7) RADIUS Success - - Ethernet successPacket = + RADIUS successPacket = constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS); - sendPacket(successPacket); - Ethernet supplicantSuccessPacket = fetchPacket(6); + aaa.radiusListener.handleRadiusPacket((successPacket)); + Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4); - checkRadiusPacket(supplicantSuccessPacket, EAP.SUCCESS); + checkRadiusPacket(aaa, supplicantSuccessPacket, EAP.SUCCESS); // State machine should be in authorized state assertThat(stateMachine, notNullValue()); assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED)); + } /** @@ -502,7 +253,7 @@ public class AAATest { public void testConfig() { assertThat(aaa.nasIpAddress.getHostAddress(), is(AAAConfig.DEFAULT_NAS_IP)); assertThat(aaa.nasMacAddress, is(AAAConfig.DEFAULT_NAS_MAC)); - assertThat(aaa.radiusIpAddress.getHostAddress(), is(AAAConfig.DEFAULT_RADIUS_IP)); + assertThat(aaa.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS)); assertThat(aaa.radiusMacAddress, is(AAAConfig.DEFAULT_RADIUS_MAC)); } } diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java new file mode 100644 index 00000000..dffcba2f --- /dev/null +++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java @@ -0,0 +1,224 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.aaa; + +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.util.LinkedList; +import java.util.List; + +import org.onlab.packet.BasePacket; +import org.onlab.packet.EAP; +import org.onlab.packet.EAPOL; +import org.onlab.packet.EthType; +import org.onlab.packet.Ethernet; +import org.onlab.packet.MacAddress; +import org.onosproject.net.packet.DefaultInboundPacket; +import org.onosproject.net.packet.DefaultPacketContext; +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.OutboundPacket; +import org.onosproject.net.packet.PacketContext; +import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketServiceAdapter; + +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.onosproject.net.NetTestTools.connectPoint; + +/** + * Common methods for AAA app testing. + */ +public class AAATestBase { + + MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a"); + MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a"); + + // Our session id will be the device ID ("of:1") with the port ("1") concatenated + static final String SESSION_ID = "of:11"; + + List<BasePacket> savedPackets = new LinkedList<>(); + PacketProcessor packetProcessor; + + /** + * Saves the given packet onto the saved packets list. + * + * @param packet packet to save + */ + void savePacket(BasePacket packet) { + savedPackets.add(packet); + } + + /** + * Keeps a reference to the PacketProcessor and saves the OutboundPackets. + */ + class MockPacketService extends PacketServiceAdapter { + + @Override + public void addProcessor(PacketProcessor processor, int priority) { + packetProcessor = processor; + } + + @Override + public void emit(OutboundPacket packet) { + try { + Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(), + 0, packet.data().array().length); + savePacket(eth); + } catch (Exception e) { + fail(e.getMessage()); + } + } + } + + /** + * Mocks the DefaultPacketContext. + */ + final class TestPacketContext extends DefaultPacketContext { + + private TestPacketContext(long time, InboundPacket inPkt, + OutboundPacket outPkt, boolean block) { + super(time, inPkt, outPkt, block); + } + + @Override + public void send() { + // We don't send anything out. + } + } + + /** + * Sends an Ethernet packet to the process method of the Packet Processor. + * + * @param reply Ethernet packet + */ + void sendPacket(Ethernet reply) { + final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize()); + InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1), + reply, + byteBuffer); + + PacketContext context = new TestPacketContext(127L, inPacket, null, false); + packetProcessor.process(context); + } + + /** + * Constructs an Ethernet packet containing identification payload. + * + * @return Ethernet packet + */ + Ethernet constructSupplicantIdentifyPacket(StateMachine stateMachine, + byte type, + byte id, + Ethernet radiusChallenge) + throws Exception { + Ethernet eth = new Ethernet(); + eth.setDestinationMACAddress(clientMac.toBytes()); + eth.setSourceMACAddress(serverMac.toBytes()); + eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort()); + eth.setVlanID((short) 2); + + String username = "testuser"; + byte[] data = username.getBytes(); + + + if (type == EAP.ATTR_MD5) { + String password = "testpassword"; + EAPOL eapol = (EAPOL) radiusChallenge.getPayload(); + EAP eap = (EAP) eapol.getPayload(); + + byte[] identifier = new byte[password.length() + eap.getData().length]; + + identifier[0] = stateMachine.challengeIdentifier(); + System.arraycopy(password.getBytes(), 0, identifier, 1, password.length()); + System.arraycopy(eap.getData(), 1, identifier, 1 + password.length(), 16); + + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] hash = md.digest(identifier); + data = new byte[17]; + data[0] = (byte) 16; + System.arraycopy(hash, 0, data, 1, 16); + } + EAP eap = new EAP(EAP.RESPONSE, (byte) 1, type, + data); + eap.setIdentifier(id); + + // eapol header + EAPOL eapol = new EAPOL(); + eapol.setEapolType(EAPOL.EAPOL_PACKET); + eapol.setPacketLength(eap.getLength()); + + // eap part + eapol.setPayload(eap); + + eth.setPayload(eapol); + eth.setPad(true); + return eth; + } + + /** + * Constructs an Ethernet packet containing a EAPOL_START Payload. + * + * @return Ethernet packet + */ + Ethernet constructSupplicantStartPacket() { + Ethernet eth = new Ethernet(); + eth.setDestinationMACAddress(clientMac.toBytes()); + eth.setSourceMACAddress(serverMac.toBytes()); + eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort()); + eth.setVlanID((short) 2); + + EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null); + + // eapol header + EAPOL eapol = new EAPOL(); + eapol.setEapolType(EAPOL.EAPOL_START); + eapol.setPacketLength(eap.getLength()); + + // eap part + eapol.setPayload(eap); + + eth.setPayload(eapol); + eth.setPad(true); + return eth; + } + + /** + * Checks the contents of a RADIUS packet being sent to the RADIUS server. + * + * @param radiusPacket packet to check + * @param code expected code + */ + void checkRadiusPacket(AAA aaa, Ethernet radiusPacket, byte code) { + + assertThat(radiusPacket.getSourceMAC(), + is(MacAddress.valueOf(aaa.nasMacAddress))); + assertThat(radiusPacket.getDestinationMAC(), is(serverMac)); + + assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class)); + EAPOL eapol = (EAPOL) radiusPacket.getPayload(); + assertThat(eapol, notNullValue()); + + assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET)); + assertThat(eapol.getPayload(), instanceOf(EAP.class)); + EAP eap = (EAP) eapol.getPayload(); + assertThat(eap, notNullValue()); + + assertThat(eap.getCode(), is(code)); + } +} diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java index 04837e85..1838c63e 100644 --- a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java +++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java @@ -21,7 +21,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; public class StateMachineTest { |