1b28a5538SAdam Hornacek /* 2b28a5538SAdam Hornacek * CDDL HEADER START 3b28a5538SAdam Hornacek * 4b28a5538SAdam Hornacek * The contents of this file are subject to the terms of the 5b28a5538SAdam Hornacek * Common Development and Distribution License (the "License"). 6b28a5538SAdam Hornacek * You may not use this file except in compliance with the License. 7b28a5538SAdam Hornacek * 8b28a5538SAdam Hornacek * See LICENSE.txt included in this distribution for the specific 9b28a5538SAdam Hornacek * language governing permissions and limitations under the License. 10b28a5538SAdam Hornacek * 11b28a5538SAdam Hornacek * When distributing Covered Code, include this CDDL HEADER in each 12b28a5538SAdam Hornacek * file and include the License file at LICENSE.txt. 13b28a5538SAdam Hornacek * If applicable, add the following below this CDDL HEADER, with the 14b28a5538SAdam Hornacek * fields enclosed by brackets "[]" replaced with your own identifying 15b28a5538SAdam Hornacek * information: Portions Copyright [yyyy] [name of copyright owner] 16b28a5538SAdam Hornacek * 17b28a5538SAdam Hornacek * CDDL HEADER END 18b28a5538SAdam Hornacek */ 19b28a5538SAdam Hornacek 20b28a5538SAdam Hornacek /* 21c6f0939bSAdam Hornacek * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. 22b28a5538SAdam Hornacek */ 23b28a5538SAdam Hornacek package opengrok.auth.plugin.configuration; 24b28a5538SAdam Hornacek 25b28a5538SAdam Hornacek import java.beans.ExceptionListener; 26b28a5538SAdam Hornacek import java.beans.XMLDecoder; 27b28a5538SAdam Hornacek import java.beans.XMLEncoder; 28b28a5538SAdam Hornacek import java.io.ByteArrayInputStream; 29b28a5538SAdam Hornacek import java.io.ByteArrayOutputStream; 30e5d05ee2SVladimir Kotal import java.io.File; 31e5d05ee2SVladimir Kotal import java.io.IOException; 32b28a5538SAdam Hornacek import java.util.ArrayList; 33b28a5538SAdam Hornacek import java.util.LinkedList; 34c6f0939bSAdam Hornacek import java.util.List; 35c6f0939bSAdam Hornacek 36b28a5538SAdam Hornacek import opengrok.auth.plugin.ldap.LdapServer; 37b28a5538SAdam Hornacek import opengrok.auth.plugin.util.WebHook; 38b28a5538SAdam Hornacek import opengrok.auth.plugin.util.WebHooks; 392f7dccc7SAdam Hornacek import org.junit.jupiter.api.Test; 40e5d05ee2SVladimir Kotal import org.junit.jupiter.params.ParameterizedTest; 41e5d05ee2SVladimir Kotal import org.junit.jupiter.params.provider.ValueSource; 42b28a5538SAdam Hornacek 432f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertEquals; 442f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull; 45e5d05ee2SVladimir Kotal import static org.junit.jupiter.api.Assertions.assertThrows; 46b28a5538SAdam Hornacek 47b28a5538SAdam Hornacek /** 48b28a5538SAdam Hornacek * 49b28a5538SAdam Hornacek * @author Krystof Tulinger 50b28a5538SAdam Hornacek */ 51*14bb522cSAdam Hornacek class ConfigurationTest { 52b28a5538SAdam Hornacek 53b28a5538SAdam Hornacek @Test testEncodeDecode()54*14bb522cSAdam Hornacek void testEncodeDecode() { 55b28a5538SAdam Hornacek // Create an exception listener to detect errors while encoding and 56b28a5538SAdam Hornacek // decoding 57b28a5538SAdam Hornacek final LinkedList<Exception> exceptions = new LinkedList<>(); 58c6f0939bSAdam Hornacek ExceptionListener listener = exceptions::addLast; 59b28a5538SAdam Hornacek 60b28a5538SAdam Hornacek ByteArrayOutputStream out = new ByteArrayOutputStream(); 61b28a5538SAdam Hornacek XMLEncoder enc = new XMLEncoder(out); 62b28a5538SAdam Hornacek enc.setExceptionListener(listener); 63b28a5538SAdam Hornacek 64b28a5538SAdam Hornacek Configuration configuration1 = new Configuration(); 65b28a5538SAdam Hornacek configuration1.setInterval(500); 66b28a5538SAdam Hornacek configuration1.setSearchTimeout(1000); 67b28a5538SAdam Hornacek configuration1.setConnectTimeout(42); 68b28a5538SAdam Hornacek configuration1.setCountLimit(10); 69c6f0939bSAdam Hornacek configuration1.setServers(new ArrayList<>(List.of(new LdapServer("http://server.com")))); 70b28a5538SAdam Hornacek WebHooks webHooks = new WebHooks(); 71b28a5538SAdam Hornacek WebHook hook = new WebHook(); 72b28a5538SAdam Hornacek hook.setContent("foo"); 73b28a5538SAdam Hornacek hook.setURI("http://localhost:8080/source/api/v1/messages"); 74b28a5538SAdam Hornacek webHooks.setFail(hook); 75b28a5538SAdam Hornacek configuration1.setWebHooks(webHooks); 76b28a5538SAdam Hornacek 77b28a5538SAdam Hornacek enc.writeObject(configuration1); 78b28a5538SAdam Hornacek enc.close(); 79b28a5538SAdam Hornacek 80b28a5538SAdam Hornacek // verify that the write didn't fail 81b28a5538SAdam Hornacek if (!exceptions.isEmpty()) { 82*14bb522cSAdam Hornacek throw new AssertionError( "Got " + exceptions.size() + " exception(s)", exceptions.getFirst()); 83b28a5538SAdam Hornacek } 84b28a5538SAdam Hornacek 85b28a5538SAdam Hornacek ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 86b28a5538SAdam Hornacek XMLDecoder dec = new XMLDecoder(in, null, listener); 87b28a5538SAdam Hornacek Configuration configuration2 = (Configuration) dec.readObject(); 88b28a5538SAdam Hornacek assertNotNull(configuration2); 89b28a5538SAdam Hornacek assertEquals(configuration1.getXMLRepresentationAsString(), 90b28a5538SAdam Hornacek configuration2.getXMLRepresentationAsString()); 91b28a5538SAdam Hornacek 92b28a5538SAdam Hornacek dec.close(); 93b28a5538SAdam Hornacek // verify that the read didn't fail 94b28a5538SAdam Hornacek if (!exceptions.isEmpty()) { 95*14bb522cSAdam Hornacek throw new AssertionError( "Got " + exceptions.size() + " exception(s)", exceptions.getFirst()); 96b28a5538SAdam Hornacek } 97b28a5538SAdam Hornacek } 98e5d05ee2SVladimir Kotal 99e5d05ee2SVladimir Kotal @ParameterizedTest 100e5d05ee2SVladimir Kotal @ValueSource(strings = { 101e5d05ee2SVladimir Kotal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 102e5d05ee2SVladimir Kotal "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 103e5d05ee2SVladimir Kotal " <object class=\"java.lang.Runtime\" method=\"getRuntime\">\n" + 104e5d05ee2SVladimir Kotal " <void method=\"exec\">\n" + 105e5d05ee2SVladimir Kotal " <array class=\"java.lang.String\" length=\"2\">\n" + 106e5d05ee2SVladimir Kotal " <void index=\"0\">\n" + 107e5d05ee2SVladimir Kotal " <string>/usr/bin/nc</string>\n" + 108e5d05ee2SVladimir Kotal " </void>\n" + 109e5d05ee2SVladimir Kotal " <void index=\"1\">\n" + 110e5d05ee2SVladimir Kotal " <string>-l</string>\n" + 111e5d05ee2SVladimir Kotal " </void>\n" + 112e5d05ee2SVladimir Kotal " </array>\n" + 113e5d05ee2SVladimir Kotal " </void>\n" + 114e5d05ee2SVladimir Kotal " </object>\n" + 115e5d05ee2SVladimir Kotal "</java>", 116e5d05ee2SVladimir Kotal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 117e5d05ee2SVladimir Kotal "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 118e5d05ee2SVladimir Kotal " <object class=\"java.lang.ProcessBuilder\">\n" + 119e5d05ee2SVladimir Kotal " <array class=\"java.lang.String\" length=\"1\" >\n" + 120e5d05ee2SVladimir Kotal " <void index=\"0\"> \n" + 121e5d05ee2SVladimir Kotal " <string>/usr/bin/curl https://oracle.com</string>\n" + 122e5d05ee2SVladimir Kotal " </void>\n" + 123e5d05ee2SVladimir Kotal " </array>\n" + 124e5d05ee2SVladimir Kotal " <void method=\"start\"/>\n" + 125e5d05ee2SVladimir Kotal " </object>\n" + 126e5d05ee2SVladimir Kotal "</java>", 127e5d05ee2SVladimir Kotal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 128e5d05ee2SVladimir Kotal "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 129e5d05ee2SVladimir Kotal " <object class = \"java.io.FileOutputStream\"> \n" + 130e5d05ee2SVladimir Kotal " <string>opengrok_test.txt</string>\n" + 131e5d05ee2SVladimir Kotal " <method name = \"write\">\n" + 132e5d05ee2SVladimir Kotal " <array class=\"byte\" length=\"3\">\n" + 133e5d05ee2SVladimir Kotal " <void index=\"0\"><byte>96</byte></void>\n" + 134e5d05ee2SVladimir Kotal " <void index=\"1\"><byte>96</byte></void>\n" + 135e5d05ee2SVladimir Kotal " <void index=\"2\"><byte>96</byte></void>\n" + 136e5d05ee2SVladimir Kotal " </array>\n" + 137e5d05ee2SVladimir Kotal " </method>\n" + 138e5d05ee2SVladimir Kotal " <method name=\"close\"/>\n" + 139e5d05ee2SVladimir Kotal " </object>\n" + 140e5d05ee2SVladimir Kotal "</java>" 141e5d05ee2SVladimir Kotal }) testDeserializationOfNotWhiteListedClassThrowsError(final String exploit)142e5d05ee2SVladimir Kotal void testDeserializationOfNotWhiteListedClassThrowsError(final String exploit) { 143e5d05ee2SVladimir Kotal assertThrows(IllegalAccessError.class, () -> Configuration.makeXMLStringAsConfiguration(exploit)); 144e5d05ee2SVladimir Kotal } 145e5d05ee2SVladimir Kotal 146e5d05ee2SVladimir Kotal @Test testReadCacheValid()147e5d05ee2SVladimir Kotal void testReadCacheValid() throws IOException { 148e5d05ee2SVladimir Kotal File testFile = new File(ConfigurationTest.class.getClassLoader(). 149e5d05ee2SVladimir Kotal getResource("opengrok/auth/plugin/configuration/plugin-config.xml").getFile()); 150e5d05ee2SVladimir Kotal Configuration config = Configuration.read(testFile); 151e5d05ee2SVladimir Kotal assertNotNull(config); 152e5d05ee2SVladimir Kotal assertEquals(2, config.getServers().size()); 153e5d05ee2SVladimir Kotal } 154b28a5538SAdam Hornacek } 155